目录
JSP(全称:Java Server Pages):Java 服务端页面。
是一种动态的网页技术,其中既可以定义 HTML、JS、CSS等静态内容
JSP = HTML + Java
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>JSP,Hello World</h1>
<%
System.out.println("hello,jsp~");
%>
</body>
</html>
上面代码 h1 标签内容是展示在页面上,而 Java 的输出语句是输出在 idea 的控制台。
JSP 作用:简化开发,避免了在Servlet中直接输出HTML标签。
JSP快速入门
导入 JSP 依赖
<!--jsp 依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
该依赖的 scope 必须设置为 provided ,因为 tomcat 中有这个jar包了,
所以在打包时是不希望将该依赖打进工程的war包中。
创建 jsp 页面
编写代码
<%@page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>JSP,Hello World</h1>
<%
System.out.println("hello,jsp~");
%>
</body>
</html>
测试
启动服务器并在浏览器地址栏输入 http://localhost:8080/jsp-demo/hello.jsp
在浏览器和idea的控制台看到输出的 hello,jsp~ 内容。
JSP 本质上就是一个 Servlet
JSP原理
1. 浏览器第一次访问 hello.jsp 页面
2. tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet
3. tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
4. tomcat 会执行该字节码文件,向外提供服务
JSP脚本
JSP 脚本有如下三个分类:
<%...%>:内容会直接放到_jspService()方法之中
<%=.%>:内容会放到out.print()中,作为out.print()的参数
<%!.%>:内容会放到_jspService()方法之外,被类直接包含
<%
System.out.println("hello,jsp~");
int i = 3;
%>
通过浏览器访问 hello.jsp 后,查看转换的 hello_jsp.java 文件,
i 变量定义在了 _jspService() 方法中
<%="hello"%>
<%=i%>
<%!
void show(){}
String name = "zhangsan";
%>
案例
需求
使用JSP脚本展示品牌数据
<%@ page import="com.green.pojo.Brand" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
//查询数据库
List<Brand> brands = new ArrayList<Brand>();
brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));
%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="新增"><br>
<hr>
<table border="1" cellspacing="0" width="800">
<tr>
<th>序号</th>
<th>品牌名称</th>
<th>企业名称</th>
<th>排序</th>
<th>品牌介绍</th>
<th>状态</th>
<th>操作</th>
</tr>
<%
for (int i = 0; i < brands.size(); i++) {
Brand brand = brands.get(i);
%>
<tr align="center">
<td><%=brand.getId()%>
</td>
<td><%=brand.getBrandName()%>
</td>
<td><%=brand.getCompanyName()%>
</td>
<td><%=brand.getOrdered()%>
</td>
<td><%=brand.getDescription()%>
</td>
<%
if (brand.getStatus() == 1) {
//显示启用
%>
<td><%="启用"%>
</td>
<%
} else {
//显示禁用
%>
<td><%="禁用"%>
</td>
<%
}
%>
<td><a href="#">修改</a> <a href="#">删除</a></td>
</tr>
<%
}
%>
</table>
</body>
</html>
JSP 缺点
书写麻烦:特别是复杂的页面
既要写 HTML 标签,还要写 Java 代码阅读麻烦
代码需要花费很长的时间去梳理
复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE.
占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存
调试困难:出错后,需要找到自动生成的.java文件进行调试
不利于团队协作:前端人员不会 Java,后端人员不精 HTML
如果页面布局发生变化,前端工程师对静态页面进行修改,然后再交给后端工程师,
由后端工程师再将该页面改为 JSP页面
JSP 已逐渐退出历史舞台,以后开发更多的是使用 HTML + Ajax 来替代
EL表达式
概述
EL(全称Expression Language )表达式语言,用于简化 JSP 页面内的 Java 代码。
EL 表达式的主要作用是 获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。
而 EL 表达式的语法也比较简单,${expression} 。
例如:${brands} 就是获取域中存储的 key 为 brands 的数据。
代码演示
定义servlet,在servlet中封装一些数据并存储到request域对象中并转发到el-demo.jsp 页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--el表达式--%>
${brands}
</body>
</html>
package com.green.web;
import com.green.pojo.Brand;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/demo1")
public class ServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、准备数据
List<Brand> brands = new ArrayList<Brand>();
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
request.getRequestDispatcher("/el-demo.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
域对象
JavaWeb中有四大域对象,分别是:
page:当前页面有效
request:当前请求有效
session:当前会话有效
application:当前应用有效
el 表达式获取数据,会依次从这4个域中寻找,直到找到为止。而这四个域对象的作用范围如下图所示
例如: ${brands},el 表达式获取数据,会先从page域对象中获取数据,
如果没有再到 requet 域对象中获取数据,如果再没有再到 session 域对象中获取,
如果还没有才会到 application 中获取数据。
JSTL标签
JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码。
导入坐标
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
在JSP页面上引入JSTL标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
使用标签
if 标签
<c:if> :相当于 if 判断
属性:test,用于定义条件表达式
<c:if test="${status == 1}">
启用
</c:if>
<c:if test="${status == 0}">
禁用
</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);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
c:if:来完成逻辑判断,替换java if else
--%>
<c:if test="${status == 1}">
启用
</c:if>
<c:if test="${status == 0}">
禁用
</c:if>
</body>
</html>
forEach 标签
<c:forEach> :相当于 for 循环。java中有增强for循环和普通for循环,
JSTL 中的 <c:forEach> 也有两种用法
用法一
类似于 Java 中的增强for循环。涉及到的 <c:forEach> 中的属性如下
items:被遍历的容器
var:遍历产生的临时变量
varStatus:遍历状态对象
如下代码,是从域对象中获取名为 brands 数据,该数据是一个集合;
遍历,并给该集合中的每一个元素起名为brand ,是 Brand对象。
在循环里面使用 EL表达式获取每一个Brand对象的属性值
<c:forEach items="${brands}" var="brand">
<tr align="center">
<td>${brand.id}</td>
<td>${brand.brandName}</td>
<td>${brand.companyName}</td>
<td>${brand.description}</td>
</tr>
</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" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="新增"><br>
<hr>
<table border="1" cellspacing="0" width="800">
<tr>
<th>序号</th>
<th>品牌名称</th>
<th>企业名称</th>
<th>排序</th>
<th>品牌介绍</th>
<th>状态</th>
<th>操作</th>
</tr>
<c:forEach items="${brands}" var="brand" varStatus="status">
<tr align="center">
<%-- <td>${brand.id}</td>--%>
<%--
index:从0开始
count:从1开始
--%>
<td>${status.count}</td>
<td>${brand.brandName}</td>
<td>${brand.companyName}</td>
<td>${brand.ordered}</td>
<td>${brand.description}</td>
<c:if test="${brand.status == 1}">
<td>启用</td>
</c:if>
<c:if test="${brand.status == 0}">
<td>禁用</td>
</c:if>
<%-- <td>${brand.status}</td>--%>
<td><a href="#">修改</a> <a href="#">删除</a></td>
</tr>
</c:forEach>
</table>
<hr>
<c:forEach begin="1" end="10" step="1" var="i">
<a href="#">${i}</a>
</c:forEach>
</body>
</html>
用法二
类似于Java中的普通for循环。涉及到的 <c:forEach> 中的属性如下
begin:开始数
end:结束数
step:步长
实例代码:
从0循环到10,变量名是 i ,每次自增1
<c:forEach begin="10" end="10" step="1" var="i">
${i}
</c:forEach>
MVC模式和三层架构
MVC 是一种分层开发的模式,其中:
M:Model,业务模型,处理业务
V:View,视图,界面展示
C:Controller,控制器,处理请求,调用模型和视图
控制器(serlvlet)用来接收浏览器发送过来的请求,控制器调用模型(JavaBean)来获取数据,
比如从数据库查询数据;控制器获取到数据后再交由视图(JSP)进行数据展示。
MVC 好处:
职责单一,互不影响。每个角色做它自己的事,各司其职。
有利于分工协作。
有利于组件重用
三层架构
表现层 、 业务逻辑层 、 数据访问层
数据访问层:对数据库的CRUD基本操作
业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。
例如 注册业务功能 ,会先调用数据访问层的selectByName()方法判断该用户名是否存在,
如果不存在再调用 数据访问层 的 insert()方法进行数据的添加操作
表现层:接收请求,封装数据,调用业务逻辑层,响应数据
浏览器发送请求,表现层的Servlet接收请求并调用业务逻辑层的方法进行业务逻辑处理,
而业务逻辑层方法调用数据访问层方法进行数据的操作,依次返回到serlvet,
然后servlet将数据交由 JSP 进行展示。
三层架构的每一层都有特有的包名称:
表现层: com.test.controller 或者 com.test.web
业务逻辑层: com.test.service
数据访问层: com.test.dao 或者 com.test.mapper
如上图上半部分是 MVC 模式,上图下半部分是三层架构。
MVC 模式中的c(控制器)和V(视图)就是三层架构中的表现层,
而MVC模式中的M(模型)就是三层架构中的业务逻辑层和数据访问层。
可以将 MVC 模式 理解成是一个大的概念,而三层架构是对MVC模式实现架构的思想。
那么以后按照要求将不同层的代码写在不同的包下,每一层里功能职责做到单一,
将来如果将表现层的技术换掉,而业务逻辑层和数据访问层的代码不需要发生变化。
案例
需求:完成品牌数据的增删改查操作
环境准备
创建新的模块 brand_demo,引入坐标
创建三层架构的包结构
数据库表 tb_brand
实体类 Brand
MyBatis 基础环境
Mybatis-config.xml
BrandMapper.xml
BrandMapper接口
创建工程
创建新的模块 brand_demo,引入坐标
mysql的驱动包
要使用mybatis框架。
mybaits的依赖包
web项目需要用到servlet和jsp。
servlet和jsp的依赖包
需要使用 jstl 进行数据展示。jstl的依赖包
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>brand-deno</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</properties>
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!--jstl-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</build>
</project>
创建包
创建不同的包结构,用来存储不同的类。包结构如下
查询所有
点击 查询所有 超链接是需要先请后端的 servlet ,
由 servlet 跳转到对应的页面进行数据的动态展示。而整个流程如下图:
编写BrandMapper
在 mapper 包下创建创建 BrandMapper 接口,在接口中定义 selectAll() 方法
/**
* 查询所有
* @return
*/
@Select("select * from tb_brand")
@ResultMap("brandResultMap")
List<Brand> selectAll();
//编写工具类
//在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;
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
//编写BrandService
//在 service 包下创建 BrandService 类
public class BrandService {
//SqlSessionFactory初始化
SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
/**
* 查询所有
* @return
*/
//调用BrandMapper.selectAll()
public List<Brand> selectAll(){
//2、调用SqlSession
SqlSession sqlSession = factory.openSession();
//3、获取BrandMa
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4、调用方法
List<Brand> brands = mapper.selectAll();
sqlSession.close();
return brands;
}
}
/*
* 编写Servlet
在 web 包下创建名为 SelectAllServlet 的 servlet ,该 servlet 的逻辑如下:
调用 BrandService 的 selectAll() 方法进行业务逻辑处理,
并接收返回的结果将上一步返回的结果存储到 request 域对象中
跳转到 brand.jsp 页面进行数据的展示
* */
@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
//创建BrandServlet对象
private BrandService service = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、调用BrandServlet完成查询
List<Brand> 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);
}
}
//编写brand.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="新增" id="add"><br>
<hr>
<table border="1" cellspacing="0" width="80%">
<tr>
<th>序号</th>
<th>品牌名称</th>
<th>企业名称</th>
<th>排序</th>
<th>品牌介绍</th>
<th>状态</th>
<th>操作</th>
</tr>
<c:forEach items="${brands}" var="brand" varStatus="status">
<tr align="center">
<%-- <td>${brand.id}</td>--%>
<%--
index:从0开始
count:从1开始
--%>
<td>${status.count}</td>
<td>${brand.brandName}</td>
<td>${brand.companyName}</td>
<td>${brand.ordered}</td>
<td>${brand.description}</td>
<c:if test="${brand.status == 1}">
<td>启用</td>
</c:if>
<c:if test="${brand.status == 0}">
<td>禁用</td>
</c:if>
<%-- <td>${brand.status}</td>--%>
<td><a href="#">修改</a> <a href="#">删除</a></td>
</tr>
</c:forEach>
</table>
<script>
document.getElementById("add").onclick = function () {
location.href = "/brand-deno/addBrand.jsp"
}
</script>
</body>
</html>
<!-- 查询到的字段名和实体类对象的属性名没有一一对应 起别名解决-->
<?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.green.mapper.BrandMapper">
<!-- 给字段起别名-->
<resultMap id="brandResultMap" type="brand">
<result column="brand_name" property="brandName"></result>
<result column="company_name" property="companyName"></result>
</resultMap>
</mapper>
添加
点击新增按钮后,会先跳转到addBrand.jsp新增页面,在该页面输入要添加的数据,
输入完毕后点击 提交 按钮,需要将数据提交到后端,而后端进行数据添加操作,
并重新将所有的数据查询出来。
编写BrandMapper方法
在 BrandMapper 接口,在接口中定义 add(Brand brand) 方法
/**
* 添加
* @param brand
*/
@Insert("insert into tb_brand values (null,#{brandName},#{companyName},#{ordered},#{description},#{status})")
void add(Brand brand);
}
编写BrandService方法
在 BrandService 类中定义添加品牌数据方法 add(Brand brand)
/**
* 添加
* @param brand
*/
public void add(Brand brand) {
//2、调用SqlSession
SqlSession sqlSession = factory.openSession();
//3、获取BrandMa
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4、调用方法
mapper.add(brand);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
}
编写addBrand.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加品牌</title>
</head>
<body>
<h3>添加品牌</h3>
<form action="/brand-deno/addServlet" method="post">
品牌名称:<input name="brandName"><br>
企业名称:<input name="companyName"><br>
排序:<input name="ordered"><br>
描述信息:<textarea rows="5" cols="20" name="description"></textarea><br>
状态:
<label><input type="radio" name="status" value="0">禁用</label>
<label><input type="radio" name="status" value="1">启用<br></label>
<input type="submit" value="提交">
</form>
</body>
</html>
编写servlet
在 web 包下创建 AddServlet 的 servlet ,该 servlet 的逻辑如下:
设置处理post请求乱码的字符集
接收客户端提交的数据
将接收到的数据封装到 Brand 对象中
调用 BrandService 的 add() 方法进行添加的业务逻辑处理
跳转到 selectAllServlet 资源重新查询数据
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
//创建BrandServlet对象
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);
}
}
修改
回显数据
要实现这个效果,那当点击 修改 按钮时不能直接跳转到 update.jsp 页面,
而是需要先带着当前行数据的 id 请求后端程序,后端程序根据 id 查询数据,
将数据存储到域对象中跳转到 update.jsp 页面进行数据展示
编写BrandMapper方法
在 BrandMapper 接口,在接口中定义 selectById(int id) 方法
/**
* 根据id查询数据
* @param id
* @return
*/
@Select("select * from tb_brand where id = #{id}")
@ResultMap("brandResultMap")
Brand selectById(int id);
编写BrandService方法
在 BrandService 类中定义根据id查询数据方法 selectById(int id)
/**
* 根据id查询数据回显
* @param id
* @return
*/
public Brand selectById(int id){
//2、调用SqlSession
SqlSession sqlSession = factory.openSession();
//3、获取BrandMa
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4、调用方法
Brand brand = mapper.selectById(id);
sqlSession.close();
return brand;
}
编写servlet
在 web 包下创建 SelectByIdServlet 的 servlet ,该 servlet 的逻辑如下:
获取请求数据 id
调用 BrandService 的 selectById() 方法进行数据查询的业务逻辑
将查询到的数据存储到 request 域对象中
跳转到 update.jsp 页面进行数据真实
@WebServlet("/selectByIdServlet")
public class SelectByIdServlet extends HttpServlet {
//创建BrandServlet对象
private BrandService service = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收id
String id = request.getParameter("id");
//1、调用service完成查询
Brand brand = service.selectById(Integer.parseInt(id));
//2、存入request域中
request.setAttribute("brand",brand);
//3、转发到update.jsp
request.getRequestDispatcher("/update.jsp").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
编写update.jsp页面
input 标签要进行数据回显,需要设置 value 属性
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改品牌</title>
</head>
<body>
<h3>修改品牌</h3>
<form action="/brand-deno/updateServlet" method="post">
品牌名称:<input name="brandName" value="${brand.brandName}"><br>
企业名称:<input name="companyName" value="${brand.companyName}"><br>
排序:<input name="ordered" value="${brand.ordered}"><br>
描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br>
状态:
<c:if test="${status == 0}">
<label><input type="radio" name="status" value="0" checked>禁用</label>
<label><input type="radio" name="status" value="1">启用<br></label>
</c:if>
<c:if test="${status == 1}">
<label><input type="radio" name="status" value="0">禁用</label>
<label><input type="radio" name="status" value="1" checked>启用<br></label>
</c:if>
<input type="submit" value="提交">
</form>
</body>
</html>
修改数据
在修改页面进行数据修改,点击 提交 按钮,会将数据提交到后端程序,
后端程序会对表中的数据进行修改操作,然后重新进行数据的查询操作。
编写BrandMapper方法
在 BrandMapper 接口,在接口中定义 update(Brand brand) 方法
/**
* 根据id修改数据
* @param brand
*/
@Update("update tb_brand set brand_name = #{brandName},company_name = #{companyName},ordered = #{ordered},description = #{description},status = #{status} where id = #{id}")
void update(Brand brand);
编写BrandService方法
在 BrandService 类中定义根据id查询数据方法 update(Brand brand)
/**
* 根据id修改数据
* @param brand
*/
public void update(Brand brand) {
//2、调用SqlSession
SqlSession sqlSession = factory.openSession();
//3、获取BrandMa
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4、调用方法
mapper.update(brand);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
编写servlet
在 web 包下创建 AddServlet 的 servlet ,该 servlet 的逻辑如下:
设置处理post请求乱码的字符集
接收客户端提交的数据
将接收到的数据封装到 Brand 对象中
调用 BrandService 的 update() 方法进行添加的业务逻辑处理
跳转到 selectAllServlet 资源重新查询数据
@WebServlet("/updateServlet")
public class UpdateServlet extends HttpServlet {
//创建BrandServlet对象
private BrandService service = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理post请求乱码问题
request.setCharacterEncoding("UTF-8");
//1、接收表单数据,封装成一个Brand对象
String id = request.getParameter("id");
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.setId(Integer.parseInt(id));
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrdered(Integer.parseInt(ordered));
brand.setDescription(description);
brand.setStatus(Integer.parseInt(status));
//2、调用service完成修改
service.update(brand);
//3、转发到查询所有Servlet
request.getRequestDispatcher("/selectAllServlet").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
存在问题:update.jsp 页面提交数据时是没有携带主键数据的,而后台修改数据需要根据主键进行修改
针对这个问题,我们不希望页面将主键id展示给用户看,但是又希望在提交数据时能将主键id提交到后端。
此时使用隐藏域,在 update.jsp 页面的表单中添加如下代码:
<%--隐藏域,提交id--%>
<input type="hidden" name="id" value="${brand.id}">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改品牌</title>
</head>
<body>
<h3>修改品牌</h3>
<form action="/brand-deno/updateServlet" method="post">
<%--隐藏域 提交id--%>
<input type="hidden" name="id" value="${brand.id}">
品牌名称:<input name="brandName" value="${brand.brandName}"><br>
企业名称:<input name="companyName" value="${brand.companyName}"><br>
排序:<input name="ordered" value="${brand.ordered}"><br>
描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br>
状态:
<c:if test="${brand.status == 0}">
<label><input type="radio" name="status" value="0" checked>禁用</label>
<label><input type="radio" name="status" value="1">启用<br></label>
</c:if>
<c:if test="${brand.status == 1}">
<label><input type="radio" name="status" value="0">禁用</label>
<label><input type="radio" name="status" value="1" checked>启用<br></label>
</c:if>
<input type="submit" value="提交">
</form>
</body>
</html>
删除数据
编写BrandMapper方法
在 BrandMapper 接口,在接口中定义 deleteById(int id) 方法
/**
* 删除
* @param id
*/
@Delete("delete from tb_brand where id = #{id}")
void deleteById(int id);
编写BrandService方法
在 BrandService 类中定义根据id删除数据方法 deleteById(int id)
/**
* 根据id删除数据
* @param id
*/
public void deleteById(int id) {
//2、调用SqlSession
SqlSession sqlSession = factory.openSession();
//3、获取BrandMa
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4、调用方法
mapper.deleteById(id);//12
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
编写servlet
在 web 包下创建 DeleteByIdServlet 的 servlet ,该 servlet 的逻辑如下:
接收客户端提交的id
调用 BrandService 的 DeleteById(int id) 方法进行删除的业务逻辑处理
跳转到 selectAllServlet 资源重新查询数据
@WebServlet("/deleteByIdServlet")
public class DeleteByIdServlet extends HttpServlet {
//创建BrandServlet对象
private BrandService service = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收id
String id = request.getParameter("id");
//2、调用service完成删除
service.deleteById(Integer.parseInt(id));
//3、转发到查询所有Servlet
request.getRequestDispatcher("/selectAllServlet").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
brand.jsp 页面的删除连接
<a href="/brand-deno/deleteByIdServlet?id=${brand.id}">删除</a></td>