文章目录
- JSP
- 1、JSP 概述
- 2、JSP 脚本和缺点
- 3、EL 表达式
- 4、JSTL标签
- 5、MVC模式和三层架构
- 6、案例
JSP
1、JSP 概述
-
JSP(全称:Java Server Pages):Java 服务端页面
(1)是一种动态的网页技术
(2)既可以定义 HTML、JS、CSS等静态内容,还可以定义 Java代码的动态内容
(3)JSP = HTML + Java
-
JSP 快速入门
-
(1)搭建环境
创建一个maven的 web 项目
pom.xml
文件内容如下:<?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>jsp-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version></plugin></plugins></build> </project>
- (2)导入 JSP 依赖
<dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope> </dependency>
scope
必须设置为provided
, 因为tomcat 中有这个jar包了,不能将这个依赖打包进工程中-
(3)创建 jsp 页面
-
编写代码
在hello.jsp
页面中书写HTML
标签和Java
代码,如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Title</title> </head> <body><h1>hello jsp</h1><%System.out.println("hello,jsp~");%> </body> </html>
- (5)测试
-
-
JSP 原理:JSP 本质上就是一个 Servlet
访问jsp时的流程:- 浏览器第一次访问
hello.jsp
页面 tomcat
会将hello.jsp
转换为名为hello_jsp.java
的一个Servlet
tomcat
再将转换的servlet
编译成字节码文件hello_jsp.class
tomcat
会执行该字节码文件,向外提供服务
- 浏览器第一次访问
2、JSP 脚本和缺点
-
JSP 脚本分类
JSP 脚本有如下三个分类:- <%…%>:内容会直接放到_jspService()方法之中
- <%=…%>:内容会放到out.print()中,作为out.print()的参数
- <%!…%>:内容会放到_jspService()方法之外,被类直接包含
-
JSP 缺点
由于 JSP页面内,既可以定义 HTML 标签,又可以定义 Java代码,造成了以下问题:- 书写麻烦:特别是复杂的页面既要写 HTML 标签,还要写 Java 代码
- 阅读麻烦
- 复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…
- 占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存
- 调试困难:出错后,需要找到自动生成的.java文件进行调试
- 不利于团队协作:前端人员不会 Java,后端人员不精 HTML
-
技术的发展
JSP 已逐渐退出历史舞台,使用 HTML + Ajax 来替代
-
第一阶段:使用
servlet
即实现逻辑代码编写,也对页面进行拼接 -
第二阶段:随着技术的发展,出现了
JSP
,人们发现JSP
使用起来比Servlet
方便很多,但是还是要在JSP
中嵌套Java
代码,也不利于后期的维护 -
第三阶段:使用
Servlet
进行逻辑代码开发,而使用JSP
进行数据展示
-
第四阶段:使用
servlet
进行后端逻辑代码开发,而使用HTML
进行数据展示,由ajax
进行动态数据展示
-
3、EL 表达式
-
概述
-
EL(全称Expression Language )表达式语言
-
用于简化 JSP 页面内的 Java 代码
-
EL 表达式的主要作用是 获取数据
-
从域对象中获取数据,然后将数据展示在页面上
-
语法:${expression}
例如:${brands} 就是获取域中存储的 key 为 brands 的数据
-
-
代码演示
-
定义servlet,在 servlet 中封装一些数据并存储到 request 域对象中并转发到
el-demo.jsp
页面@WebServlet("/demo1") public class ServletDemo1 extends HttpServlet {@Overrideprotected 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.jsprequest.getRequestDispatcher("/el-demo.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }
-
在
el-demo.jsp
中通过 EL表达式 获取数据<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Title</title> </head> <body>${brands} </body> </html>
-
在浏览器的地址栏输入
http://localhost:8080/jsp-demo/demo1
,页面效果如下:
-
-
域对象
JavaWeb中有四大域对象- page:当前页面有效
- request:当前请求有效
- session:当前会话有效
- application:当前应用有效
el 表达式获取数据,会依次从这4个域中寻找,直到找到为止
4、JSTL标签
-
概述
JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码
-
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>
- 在JSP页面上引入JSTL标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- 使用标签
- 导入坐标
-
if 标签
<c:if>
:相当于 if 判断,属性:test,用于定义条件表达式<c:if test="${flag == 1}">男 </c:if> <c:if test="${flag == 2}">女 </c:if>
-
forEach 标签
<c:forEach>
:相当于 for 循环。java中有增强for循环和普通for循环,JSTL 中的<c:forEach>
也有两种用法- 用法一
- items:被遍历的容器
- var:遍历产生的临时变量
- varStatus:遍历状态对象
<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>
- 用法二
- begin:开始数
- end:结束数
- step:步长
<c:forEach begin="0" end="10" step="1" var="i">${i} </c:forEach>
- 用法一
5、MVC模式和三层架构
-
MVC模式
MVC 是一种分层开发的模式,其中:- M:Model,业务模型,处理业务
- V:View,视图,界面展示
- C:Controller,控制器,处理请求,调用模型和视图
控制器(serlvlet)用来接收浏览器发送过来的请求,控制器调用模型(JavaBean)来获取数据,比如从数据库查询数据;控制器获取到数据后再交由视图(JSP)进行数据展示
- MVC 好处:
- 职责单一,互不影响。每个角色做它自己的事,各司其职。
- 有利于分工协作。
- 有利于组件重用
-
三层架构
-
数据访问层:对数据库的CRUD基本操作
-
业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如
注册业务功能
,我们会先调用数据访问层
的selectByName()
方法判断该用户名是否存在,如果不存在再调用数据访问层
的insert()
方法进行数据的添加操作 -
表现层:接收请求,封装数据,调用业务逻辑层,响应数据
-
三层架构的每一层都有特有的包名称:
- 表现层:
com.itheima.controller
或者com.itheima.web
- 业务逻辑层:
com.itheima.service
- 数据访问层:
com.itheima.dao
或者com.itheima.mapper
- 表现层:
-
-
MVC 和 三层架构
三层架构
是对MVC 模式
实现架构的思想
6、案例
-
需求:完成品牌数据的增删改查操作
-
环境准备
- 创建新的模块 brand_demo,引入坐标
- 创建三层架构的包结构
- 数据库表 tb_brand
- 实体类 Brand
- MyBatis 基础环境
- Mybatis-config.xml
- BrandMapper.xml
- BrandMapper接口
- 编写工具类
-
查询所有
-
(1)编写BrandMapper
在mapper
包下创建创建BrandMapper
接口,在接口中定义selectAll()
方法@Select("select * from tb_brand") List<Brand> selectAll();
-
(2) 编写BrandService
public class BrandService {SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();/*** 查询所有* @return*/public List<Brand> selectAll(){//调用BrandMapper.selectAll()//2. 获取SqlSessionSqlSession sqlSession = factory.openSession();//3. 获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4. 调用方法List<Brand> brands = mapper.selectAll();sqlSession.close();return brands;} }
-
(3) 编写Servlet
在web
包下创建名为SelectAllServlet
的servlet
,该servlet
的逻辑如下:- 调用
BrandService
的selectAll()
方法进行业务逻辑处理,并接收返回的结果 - 将上一步返回的结果存储到
request
域对象中 - 跳转到
brand.jsp
页面进行数据的展示
@WebServlet("/selectAllServlet") public class SelectAllServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 调用BrandService完成查询List<Brand> brands = service.selectAll();//2. 存入request域中request.setAttribute("brands",brands);//3. 转发到brand.jsprequest.getRequestDispatcher("/brand.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }
- 调用
-
(4)编写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> <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>--%><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 != 1}"><td>禁用</td></c:if><td><a href="/brand-demo/selectByIdServlet?id=${brand.id}">修改</a> <a href="#">删除</a></td></tr></c:forEach> </table> </body> </html>
-
(5)测试
使用resultMap
标签定义映射关系<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itheima.mapper.BrandMapper"><resultMap id="brandResultMap" type="brand"><result column="brand_name" property="brandName"></result><result column="company_name" property="companyName"></result></resultMap> </mapper>
并且在
BrandMapper
接口中的selectAll()
上使用@ResuleMap
注解指定使用该映射/*** 查询所有* @return*/ @Select("select * from tb_brand") @ResultMap("brandResultMap") List<Brand> selectAll();
-
-
添加
-
(1)编写BrandMapper方法
在BrandMapper
接口,在接口中定义add(Brand brand)
方法@Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})") void add(Brand brand);
-
(2)编写BrandService方法
在BrandService
类中定义添加品牌数据方法add(Brand brand)
public void add(Brand brand){//2. 获取SqlSessionSqlSession sqlSession = factory.openSession();//3. 获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4. 调用方法mapper.add(brand);//提交事务sqlSession.commit();//释放资源sqlSession.close();}
-
(3)编写servlet
在web
包下创建AddServlet
的servlet
,该servlet
的逻辑如下:- 设置处理post请求乱码的字符集
- 接收客户端提交的数据
- 将接收到的数据封装到
Brand
对象中 - 调用
BrandService
的add()
方法进行添加的业务逻辑处理 - 跳转到
selectAllServlet
资源重新查询数据
@WebServlet("/addServlet") public class AddServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected 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. 转发到查询所有Servletrequest.getRequestDispatcher("/selectAllServlet").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }
-
(4)编写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-demo/addServlet" method="post">品牌名称:<input name="brandName"><br>企业名称:<input name="companyName"><br>排序:<input name="ordered"><br>描述信息:<textarea rows="5" cols="20" name="description"></textarea><br>状态:<input type="radio" name="status" value="0">禁用<input type="radio" name="status" value="1">启用<br><input type="submit" value="提交"> </form> </body> </html>
-
(5)修改brand.jsp页面
添加新增
按钮<input type="button" value="新增" id="add"><br>
并给该按钮绑定单击事件,当点击了该按钮需要跳转到
brand.jsp
添加品牌数据的页面<script>document.getElementById("add").onclick = function (){location.href = "/brand-demo/addBrand.jsp";} </script>
-
(6) 测试
-
-
修改 - 回显数据
-
(1)编写BrandMapper方法
在BrandMapper
接口,在接口中定义selectById(int id)
方法@Select("select * from tb_brand where id = #{id}")@ResultMap("brandResultMap")Brand selectById(int id);
-
(2)编写BrandService方法
在BrandService
类中定义根据id查询数据方法selectById(int id)
public Brand selectById(int id){//调用BrandMapper.selectAll()//2. 获取SqlSessionSqlSession sqlSession = factory.openSession();//3. 获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4. 调用方法Brand brand = mapper.selectById(id);sqlSession.close();return brand;}
-
(3)编写servlet
在web
包下创建SelectByIdServlet
的servlet
,该servlet
的逻辑如下- 获取请求数据
id
- 调用
BrandService
的selectById()
方法进行数据查询的业务逻辑 - 将查询到的数据存储到 request 域对象中
- 跳转到
update.jsp
页面进行数据真实
@WebServlet("/selectByIdServlet") public class SelectByIdServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 接收idString id = request.getParameter("id");//2. 调用service查询Brand brand = service.selectById(Integer.parseInt(id));//3. 存储到request中request.setAttribute("brand",brand);//4. 转发到update.jsprequest.getRequestDispatcher("/update.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }
- 获取请求数据
-
(4)编写update.jsp页面
拷贝addBrand.jsp
页面,改名为update.jsp
并做出以下修改:title
标签内容改为修改品牌
form
标签的action
属性值改为/brand-demo/updateServlet
input
标签要进行数据回显,需要设置value
属性textarea
标签要进行数据回显,需要在标签体中使用EL表达式
- 单选框使用
if
标签需要判断brand.status
的值是 1 还是 0 在指定的单选框上使用checked
属性,表示被选中状态
<%@ 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-demo/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="${brand.status == 0}"><input type="radio" name="status" value="0" checked>禁用<input type="radio" name="status" value="1">启用<br></c:if><c:if test="${brand.status == 1}"><input type="radio" name="status" value="0" >禁用<input type="radio" name="status" value="1" checked>启用<br></c:if><input type="submit" value="提交"> </form> </body> </html>
-
(5)测试
-
-
修改 - 修改数据
-
(1)编写BrandMapper方法
在BrandMapper
接口,在接口中定义update(Brand 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);
-
(2)编写BrandService方法
在BrandService
类中定义根据id查询数据方法update(Brand brand)
public void update(Brand brand){//2. 获取SqlSessionSqlSession sqlSession = factory.openSession();//3. 获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4. 调用方法mapper.update(brand);//提交事务sqlSession.commit();//释放资源sqlSession.close();}
-
(3)编写servlet
在web
包下创建AddServlet
的servlet
,该servlet
的逻辑如下:- 设置处理post请求乱码的字符集
- 接收客户端提交的数据
- 将接收到的数据封装到
Brand
对象中 - 调用
BrandService
的update()
方法进行添加的业务逻辑处理 - 跳转到
selectAllServlet
资源重新查询数据
@WebServlet("/updateServlet") public class UpdateServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected 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. 转发到查询所有Servletrequest.getRequestDispatcher("/selectAllServlet").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }
-
(4)修改update.jsp
在update.jsp
页面的表单中添加如下代码:<%--隐藏域,提交id--%> <input type="hidden" name="id" value="${brand.id}">
-
(5)测试
-