一、JSP简介
1.1 基本概念
JSP(全称Java Server Pages)Java服务端页面技术,是JavaEE平台下的技术规范。它允许使用特定的标签在HTML网页中插入Java代码,实现动态页面处理,所以JSP就是HTML与Java代码的复合体。JSP技术可以快速的实现一个页面的开发,相比在Servlet中实现页面开发将变得更加容易。
常用的视图层技术:HTML、JSP、Thymeleaf等。
前后端分离开发方式
在前后端分离的项目中真正可以做到“术业有专攻”(开发人员分离) 。前后端分离开发方式中前端页面由专业团队完成页面的开发,并通过请求调用后端的api接口进行数据交互。
在开发前端页面的团队中更多关注的技术如:html、CSS、jQuery、Vue、Nodejs等前端技术。前端追求的是:页面表现,速度流畅,兼容性,用户体验等等。
而后端团队则更多的是业务的具体实现。在后端开发的团队中更多关注的技术如:设计模式、分布式架构、微服务架构、数据库的操作、Java的性能优化以及数据库优化等技术。前后端分离已成为互联网项目开发的业界标准使用方式,特别是为大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如:浏览器,车载终端,安卓,IOS等等)打下坚实的基础。
1.2 运行原理
1.2.1 JSP技术特点
JSP和Servlet是本质相同的技术。当一个JSP文件第一次被请求时,JSP引擎会将该JSP编译成一个Servlet,并执行这个Servlet。如果JSP文件被修改了,那么JSP引擎会重新编译这个JSP。
JSP引擎对JSP编译时会生成两个文件分别是.java
的源文件以及编译后的.class
文件,并放到Tomcat的work目录的Catalina对应的虚拟主机目录中的org\apache\jsp目录中。两个文件的名称会使用JSP的名称加”_jsp”表示。如:index_jsp.java、index_jsp.class。
1.2.2 JSP与Servlet区别
- JSP以源文件形式部署到容器中;而Servlet需要编译成class文件后部署到容器中;
- JSP部署到web项目的根目录下或根目录下的其他子目录,即静态同资源位于相同位置;而Servlet需要部署到
WEB-INF/classes
目录中。 - JSP中的HTML代码会被JSP引擎放入到Servlet的
out.write()
方法中;而在Servlet中我们需要自己通过对字符流输出流的操作生成响应的页面; - JSP更擅长表现于页面显示,Servlet更擅长于逻辑控制。
二、JSP标签
2.1 原始标签
JSP的原始标签在JSP的任何版本中都可以使用。
也叫做“脚本Scriptlet”
- <%! %> 定义方法-全局变量;
- <% %> 存储java语句-局部变量;
- <%= %> 输出表达式;
要点:
- 修改web.xml、配置文件、java需要重启tomcat服务器,但是修改jsp、html、css、js则不需要重启服务器;
- 想要在网页上输出换行需要在
out.print("<br/>")
或<%="<br/>"%>
可以直接解析html代码; - out.print 与 out.println 无区别且均不输出换行;
2.1.1 声明标签 <%! %>
声明标签用于在JSP中定义成员变量与方法的定义。标签中的内容会出现在JSP被编译后的Servlet的class的{}
中。
举例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%!
int a = 10; // 成员变量
int add(int a, int b) // 成员方法
{
return a + b;
}
%>
</body>
</html>
剖析:在当前.jsp
文件被JSP引擎转译成的.java
文件中,我们可以看到<%! %>
中的内容(变量、方法)都被存放在了Servlet的类括号{}
中作为类的成员;
2.1.2 脚本标签 <% %>
脚本标签用于在JSP中编写业务逻辑。标签中的内容会出现在JSP被编译后的Servlet的_jspService方法体中。
不能定义方法,可以定义变量、分支循环等基于业务的开发;
2.1.3 赋值标签 <%= %>
赋值标签用于在JSP中做内容输出。标签中的内容会出现在_jspService方法的out.print()
方法的参数中。注意我们在使用赋值标签时不需要在代码中添加 ':'
。
案例1:JSP原始标签的使用
<%@ page import="java.util.Random" %><%--
Created by IntelliJ IDEA.
User: kkkkkkk
Date: 2023/8/8
Time: 14:44
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int flag = new Random().nextInt(100);
String ans = "";
if(flag < 20) ans = "中奖了";
else ans = "再试试";
%>
<%= ans + flag%>
</body>
</html>
注意:<% %>中不支持嵌套<%= %>,所以需要单独使用;
2.2 指令标签
JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。
基础格式:
<%@ directive attribute="value" %>
指令可以有很多个属性,它们以键值对的形式存在,并用逗号隔开。
JSP中的三种指令标签:
<%@ page ... %> | 配置JSP页面;定义网页依赖属性,比如脚本语言、error页面、缓存需求等; |
<%@ include ... %> | 包含其他文件;导入页面资源文件; |
<%@ taglib ... %> | 引入标签库的定义,导入资源; |
2.2.1 Page指令
Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令。
语法格式:
<%@ page attribute="value" %>
等价的XML格式:
<jsp:directive.page attribute="value" />
指令属性
属性 | 描述 |
buffer | 指定out对象使用缓冲区的大小 |
autoFlush | 控制out对象的 缓存区 |
contentType | 指定当前JSP页面的MIME类型和字符编码(浏览器解析jsp的编码) |
errorPage | 指定当JSP页面发生异常时需要转向的错误处理页面 |
isErrorPage | 指定当前页面是否可以作为另一个JSP页面的错误处理页面 |
extends | 指定servlet从哪一个类继承 |
import | 导入要使用的Java类(导包) |
info | 定义JSP页面的描述信息 |
isThreadSafe | 指定对JSP页面的访问是否为线程安全 |
language | 定义JSP页面所用的脚本语言,默认是Java |
session | 指定JSP页面是否使用session |
isELIgnored | 指定是否执行EL表达式 |
isScriptingEnabled | 确定脚本元素能否被使用 |
- import属性:
- session属性:
- buffer属性:
内置输出流对象out负责将服务器的某些信息或运行结果发送到客户端显示,buffer属性用来指定out设置的缓冲区的大小或不使用缓冲区;
- autoFlush属性:
- PageEncoding和ContextType两种属性的区别:
- isThreadSafe属性:
注意:但是如果页面要实现高并发,设置为false是不当的且不能发挥性能的,因为这样直接掐死了多线程。
⭕ 正确的是设置同步互斥操作:
- info属性
- errorPage属性:
2.2.2 Include指令
JSP可以通过Include指令来包含其他文件,可以是JSP文件,HTML或文本文件。这些文件内嵌在JSP文件中,会被同时编译执行。
Include指令就是在JSP文件中包含一个静态的文件,同时解析这个文件的JSP语句。
<%@ include file="文件相对 url 地址" %>
Include 指令中的文件名实际上是一个相对的 URL 地址。如果没有给文件关联一个路径,JSP编译器默认在当前路径下寻找。
服务器每次都要检查include指令标记嵌入的文件是否被修改过,因此,JSP页面成功静态嵌入一个文件后,如果对嵌入的文件进行了修改,那么服务器会重新编译JSP页面,即将当前的JSP页面和修改后的文件合并成一个JSP页面,然后服务器再将这个新的JSP页面转译成Java类文件。
2.2.3 taglib指令
导入标签库:<%@taglib prefix="前缀名" uri="名称空间" %>
三、内置对象
JSP 使用 Java 定义的内置对象来访问网页的动态内容;内置对象只对表达式和Scriptlet有用,在声明中不能使用;
- out对象
out 对象是JspWriter类型的对象;负责向客户端输出内容;
- response对象
response 对象是 HttpServletResponse类型的对象。
- session对象
session 对象是HttpSession类型的对象。只有在包含 session=“true” 的页面中才可以被使用。
- application对象
application 对象是ServletContext类型的对象;
- config 对象
config 对象是ServletConfig类型的对象;
- pageContext 对象
pageContext 对象是PageContext类型的对象。作用是取得任何范围的参数,通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用 pageContext对象。
- page 对象
page 对象代表JSP本身;
- exception 对象
exception 对象的作用是显示异常信息,只有在包含 isErrorPage="true" 的页面中才可以被使用;
3.1 request对象
请求对象:存储“客户端”向服务器发送的请求信息;
请求报文结构:
示意图:
作用:
- 取得请求参数的值;
- 操作request范围的属性;
- 执行include指令或forward指令。
常见方法:
- request获取请求参数的值:
最好是先设置好解码方式(应与发送请求的页面的编码方式相同);
3.1.1 请求转发
请求转发是服务端的一种请求方式,相当于在服务端中直接请求某个资源。
RequestDispatcher dispatcher = request.getRequestDispatcher("/test.jsp");
dispatcher.forward(request,response);
简写方式:
request.getRequestDispatcher("/test.jsp").forword(request,response);
请求转发与重定向的区别:
- 请求转发对于客户端浏览器而言是在一次请求与响应中完成的,而重定向是在两次请求和响应中完成的;
- 请求转发并不会改变客户端浏览器地址栏中的内容;而重定向会改变客户端浏览器地址栏中内容;
- 请求转发可以通过使用request对象进行数据传递(
request.setAttribute("key")
);而重定向不能; - 如果是处理DML操作,建议使用重定向方式为客户端浏览器产生响应,可以解决表单重复提交的现象;
请求转发 | 重定向 | |
地址栏是否改变 | 不变 | 改变 |
是否保留第一次请求的数据 | 保留 | 不保留 |
客户端请求及响应的次数 | 1 | 2 |
跳转发生的位置 | 服务端 | 客户端发出的第二次跳转 |
案例1:请求转发
需求:在Servlet中获取客户端浏览器所支持的语言,并通过JSP页面将客户端浏览器所支持的语言响应给客户端浏览器。
思路:创建一个Servlet用于获取请求中的Accept-Language
头部信息,将其存入request对象中,通过请求转发的方式传给showMsg.jsp
进行美化输出;
- 创建Servlet获取request中的头部信息;
@WebServlet("/language.do")
public class LanguageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取头部信息
String header = req.getHeader("Accept-Language");
// 存入req对象中
req.setAttribute("header",header);
// 请求转发
req.getRequestDispatcher("showMsg.jsp").forward(req,resp);
}
}
- 创建jsp页面接收请求转发并获取数据输出到客户端浏览器;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
String lang = (String) request.getAttribute("header");
%>
<font color = "blue"> <%= lang%></font>
</body>
</html>
- 测试
3.3 session对象
session 对象是HttpSession类型的对象。只有在包含 session=“true”
的页面中才可以被使用。
Session对象创建过程分析
HttpSession对象是通过request.getSession()
方法来创建的。当客户端浏览器访问服务端浏览器的资源时,如果Servlet代码中含有创建Session的语句,那么就会查看request请求中有没有名为JESSIONID的Cookie。
- 当浏览器客户端首次发送请求服务器的资源时,request请求中没有对应的cookie,那么getSession()方法就会创建新的HttpSession对象,并生成一个JSESSIONID,并将其作为Session对象的键,存储在HttpSessionMap中;同时以JSESSIONID作为新的状态Cookie的key,id值为value通过Response对象返回给客户端浏览器;
- 当相同客户端浏览器第二次访问服务器时,执行到响应的request.getSession()语句时,会查找到请求中的Cookie数组中的JSESSIONID,在HttpSessionMap找是否有匹配的键值对,如果有则直接返回匹配的session对象;否则创建新的Session对象、生成JsessionId与对应的Cookie返回给客户端;
getSession()方法还有一个重载方法getSession(true|false)。当参数为true时与getSession()方法作用相同。当参数为false时则只去根据jsessionid查找是否有与这个客户端浏览器对应的HttpSession,如果有则返回,如果没有jsessionid则不会创建新的HttpSession对象。
客户端第一次请求服务端时:服务器会查看客户端是否有cookie的JSESSIONID与自身存储的SESSIONID匹配,无则会产生一个会话session对象(用于保存该客户的信息)。并且每一个session对象都会有一个唯一的SESSIONID;接着服务端会产生一个cookie,并且该cookie(name : JSESSIONID,value = SESSIONID);服务器会在响应客户端的同时,将该cookie发送给客户端。至此,客户端就有了一个cookie,同时客户端的cookie可以和服务器的session一一对应;
客户端第二/n次请求服务端时:服务端会用客户端cookie的JSESSIONID与自身的SESSIONID去匹配,匹配成功则说明不是第一次访问;
3.4 四大作用域对象
作用域即“数据共享的范围”,也就是说数据能够在多大的范围内有效。
对象名称 | 作用范围 |
application | 整个应用都有效 |
session | 在当前会话中有效 |
request | 在当前请求中有效 |
page | 在当前页面有效 |
由小到大排序范围:
- Page对象:当前页面有效;
// pageContext.jsp
<body>
<%
pageContext.setAttribute("hello", "world");
%>
<%System.out.println("页面:PageContext.jsp: " + pageContext.getAttribute("hello")); %>
<%
request.getRequestDispatcher("page1.jsp").forward(request, response);
%>
</body>
// page1.jsp
</head>
<body>
<% System.out.println("页面:page1.jsp: " + pageContext.getAttribute("hello"));%>
</body>
</html>
//输出结果
页面:PageContext.jsp: world
页面:page1.jsp: null
分析:可见,再将页面跳转出当前页面后,原页面pageContext对象设置的属性不再保留,即pageContext的作用域为当前页面。
- request对象:
//运行结果
页面:PageContext.jsp: pG rQ
页面:page1.jsp: null rQ
分析:将页面跳转出当前页面后,原页面的request对象设置的属性会被保留,即request的作用域会同一次请求;
Q:如果跳转的方式不是请求转发而是重定向呢?区别是?
先看结果:
页面:PageContext.jsp: pG rQ
页面:page1.jsp: null null
由于重定向是两次请求,因此第一次请求中的request对象在第二次请求中不会保存,所以输出的结果为null;
- session对象:同一会话内有效;切换浏览器无效,但支持同一个浏览器内的随意跳转切换页面;
- application对象:全局有效,针对当前项目的运行期间都有效(切换浏览器也可以);
四、JSTL标签库
JSTL(Java server pages standard tag library,即JSP标准标签库)JSTL标签是基于JSP页面的。这些标签可以插入在JSP代码中,本质上JSTL也是提前定义好的一组标签,这些标签封装了不同的功能,在页面上调用标签时,就等于调用了封装起来的功能。JSTL的目标是使JSP页面的可读性更强、简化JSP页面的设计、实现了代码复用、提高效率。
在JSP2.0版本后开始支持JSTL标签库。在使用JSTL标签库时需要在JSP中添加对应的taglib指令标签。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
4.1 JSTL标签分类
核心标签:常用、最重要,也是最基本的标签;
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
标签 | 描述 |
用于在JSP中显示数据,就像<%= ... > | |
用于保存数据 | |
用于删除数据 | |
用来处理产生错误的异常状况,并且将错误信息储存起来 | |
与我们在一般程序中用的if一样 | |
本身只当做<c:when>和<c:otherwise>的父标签 | |
<c:choose>的子标签,用来判断条件是否成立 | |
<c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行 | |
检索一个绝对或相对 URL,然后将其内容暴露给页面 | |
基础迭代标签,接受多种集合类型 | |
根据指定的分隔符来分隔内容并迭代输出 | |
用来给包含或重定向的页面传递参数 | |
重定向至一个新的URL. | |
使用可选的查询参数来创造一个URL |
格式化标签:JSTL格式化标签用来格式化并输出文本、日期、时间、数字。
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
标签 | 描述 |
使用指定的格式或精度格式化数字 | |
解析一个代表着数字,货币或百分比的字符串 | |
使用指定的风格或模式格式化日期和时间 | |
解析一个代表着日期或时间的字符串 | |
绑定资源 | |
指定地区 | |
绑定资源 | |
指定时区 | |
指定时区 | |
显示资源配置文件信息 | |
设置request的字符编码 |
sql标签:JSTL SQL标签库提供了与关系型数据库(Oracle,MySQL,SQL Server等等)进行交互的标签。
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
标签 | 描述 |
指定数据源 | |
运行SQL查询语句 | |
运行SQL更新语句 | |
将SQL语句中的参数设为指定值 | |
将SQL语句中的日期参数设为指定的java.util.Date 对象值 | |
在共享数据库连接中提供嵌套的数据库行为元素,将所有语句以一个事务的形式来运行 |
xml标签:JSTL XML标签库提供了创建和操作XML文档的标签。
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
在使用xml标签前,你必须将XML 和 XPath 的相关包拷贝至你的<Tomcat 安装目录>\lib下:
- XercesImpl.jar下载地址: Index of /xerces/j
- xalan.jar下载地址: Xalan-Java Version 2.7.1
标签 | 描述 |
与<%= ... >,类似,不过只用于XPath表达式 | |
解析 XML 数据 | |
设置XPath表达式 | |
判断XPath表达式,若为真,则执行本体中的内容,否则跳过本体 | |
迭代XML文档中的节点 | |
<x:when>和<x:otherwise>的父标签 | |
<x:choose>的子标签,用来进行条件判断 | |
<x:choose>的子标签,当<x:when>判断为false时被执行 | |
将XSL转换应用在XML文档中 | |
与<x:transform>共同使用,用于设置XSL样式表 |
JSTL函数:JSTL包含一系列标准函数,大部分是通用的字符串处理函数;
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
函数 | 描述 |
测试输入的字符串是否包含指定的子串 | |
测试输入的字符串是否包含指定的子串,大小写不敏感 | |
测试输入的字符串是否以指定的后缀结尾 | |
跳过可以作为XML标记的字符 | |
返回指定字符串在输入字符串中出现的位置 | |
将数组中的元素合成一个字符串然后输出 | |
返回字符串长度 | |
将输入字符串中指定的位置替换为指定的字符串然后返回 | |
将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回 | |
测试输入字符串是否以指定的前缀开始 | |
返回字符串的子集 | |
返回字符串在指定子串之后的子集 | |
返回字符串在指定子串之前的子集 | |
将字符串中的字符转为小写 | |
将字符串中的字符转为大写 | |
移除首尾的空白符 |
4.2 EL表达式
EL(Expression Language)是一种表达式语言。是为了使JSP写起来更加简单,减少java代码,可以使得获取存储在Java对象中的数据变得非常简单。在JSP2.0版本后开始支持EL表达式。
语法结构:
- ${表达式}
- ${对象.属性名}
操作符:
操作符 | 描述 |
( ) | 优先级 |
+ | 加 |
- | 减或负 |
* | 乘 |
/ 或div | 除 |
% 或 mod | 取模 |
== 或 eq | 测试是否相等 |
!= 或 ne | 测试是否不等 |
< 或 lt | 测试是否小于 |
> 或gt | 测试是否大于 |
<= or le | 测试是否小于等于 |
>= 或 ge | 测试是否大于等于 |
&& 或 and | 测试逻辑与 |
|| 或 or | 测试逻辑或 |
! 或not | 测试取反 |
empty | 测试是否空值 |
隐含对象:
隐含对象 | 描述 |
pageScope | page 作用域 |
requestScope | request 作用域 |
sessionScope | session 作用域 |
applicationScope | application 作用域 |
param | Request 对象的参数,字符串 |
paramValues | Request对象的参数,字符串集合 |
header | HTTP 信息头,字符串 |
headerValues | HTTP 信息头,字符串集合 |
initParam | 上下文初始化参数 |
cookie | Cookie值 |
pageContext | 当前页面的pageContext |
使用EL表达式取出作用域中的值:
- ${pageScope.name}
- ${requestScope.name}
- ${sessionScope.name}
- ${applicationScope.name}
获取作用域属性中的数据时,也可以只写属性名,EL表达式会按照pageScope、requestScope、sessionScope、applicationScope的顺序查找该属性的值。
- ${name}
4.3 标签实操
4.3.1 <c:if>标签的使用
<c:if>标签:判断表达式的值,如果表达式的值为 true 则执行其主体内容。
<%@ 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 test="${ 1 == 1}"> 嵌套了EL表达式
Hello JSTL!
</c:if>
</body>
</html>
4.3.2 <c:choose >标签的使用
< c:choose >, < c:when >, < c:otherwise >标签:< c:choose >标签与Java switch语句的功能一样,用于在众多选项中做出选择;
类比:switch语句中有case,而< c:choose >标签中对应有< c:when >,switch语句中有default,而< c:choose >标签中有< c:otherwise >;
<c:choose>
<c:when test = "${1==1}">
Hello when 1
</c:when>
<c:when test = "${1==1}">
Hello when 2
</c:when>
<c:otherwise>
Hello OtherWise
</c:otherwise>
</c:choose>
控制台输出:
Hello JSTL! Hello when 1
分析:
- 多个when都满足时,会选取第一个匹配到的when进行执行;
- 没有when满足时,才会执行<c:otherwise>中的内容;
4.3.3 <c:foreach>标签的使用
迭代器,用于迭代集合。
属性 | 描述 |
items | 被迭代的集合 |
begin | 迭代器的起始因子 |
end | 迭代器的结束因子 |
step | 迭代因子的增长数 |
var | 代表当前迭代元素的变量名称 |
varStatus | 代表循环状态的变量名称 |
其中,对于varStatus属性有如下参数:
current: 当前这次迭代的(集合中的)项
index: 当前这次迭代从 0 开始的迭代索引
count: 当前这次迭代从 1 开始的迭代计数
first: 用来表明当前这轮迭代是否为第一次迭代的标志
last: 用来表明当前这轮迭代是否为最后一次迭代的标志
begin: 属性值
end: 属性值
step: 属性值
举例:
<c:forEach begin = "0" end="9" step="2" varStatus="it">
forEach ${it.count}, ${it.first}, ${it.last}, ${it.index}<br>
</c:forEach>
案例1:使用<c:foreach>标签迭代List
需求:
- 创建Users对象,含有userid,username属性;
- 创建一个Servlet,在Servlet中创建多个Users对象并放到List集合中,在showUsers.jsp的页面中显示所有的Users对象的信息;
实现:
- 创建类User存储对象模型:
public class User {
private Integer userId;
private String userName;
public User(Integer userId, String userName) {
this.userId = userId;
this.userName = userName;
}
public User() {
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
- 创建servlet模拟接收请求并将用户数据传递给视图界面:
@WebServlet("/findUser.do")
public class FindUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建测试数据
User u1 = new User(1,"lmk");
User u2 = new User(2,"kk");
// 实例化List
List<User> list = new ArrayList<>();
list.add(u1);
list.add(u2);
// 将list添加入请求对象中
req.setAttribute("list",list);
// 请求转发
req.getRequestDispatcher("showUser.jsp").forward(req,resp);
}
}
- 创建视图层界面,获取请求中的数据并美化输出:
<%@ 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>
<table border = "1" align = "center">
<tr>
<th>用户ID</th>
<th>用户姓名</th>
</tr>
<c:forEach items="${requestScope.list}" var = "u">
<tr>
<td>${u.userId}</td>
<td>${u.userName}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
- 测试结果
案例2:使用<c:foreach>标签迭代Map
需求:
- 创建Users对象,含有userid,username属性;
- 创建一个Servlet,在Servlet中创建多个Users对象并放到Map集合中,在showUsers2.jsp的页面中显示所有的Users对象的信息;
实现:
- 创建Servlet传递数据给jsp视图:
@WebServlet("/findUser2.do")
public class FindUserServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建测试数据
User u1 = new User(1,"lmk");
User u2 = new User(2,"kk");
// 实例化Map
Map<String,User> map = new HashMap<>();
// 将list添加入请求对象中
map.put("user1",u1);
map.put("user2",u2);
req.setAttribute("map",map);
// 请求转发
req.getRequestDispatcher("showUser2.jsp").forward(req,resp);
}
}
- 创建视图jsp接收请求数据并美化输出:
<%@ 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>
<table border = "1" align = "center">
<tr>
<th>key</th>
<th>用户ID</th>
<th>用户姓名</th>
</tr>
<c:forEach items="${requestScope.map}" var = "u">
<tr>
<td>${u.key}</td>
<td>${u.value.userId}</td>
<td>${u.value.userName}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
- 测试结果
4.4 fmt标签的使用
JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
对日期的格式化处理
<fmt:formatDate value="${data}" pattern="yyyy-MM-dd"/>
对数字格的式化处理
<fmt:formatNumber value="${balance}" type="currency"/>
五、MVC模式
MVC模式:Model、View、Controller即模型、视图、控制器。是一种软件架构模式(Architecture pattern)。
MVC要实现的目标是将软件的用户界面和业务逻辑分离,可提高代码可扩展性、可复用性、可维护性、以及灵活性。
- View(视图):用户的操作界面。如:html、jsp。
- Model(模型):具体的业务模型与数据模型。如:service、dao、pojo。
- Controller(控制):处理从视图层发送的请求,并选取模型层的业务模型完成响应的业务实现,并产生响应。如:Servlet。
5.1 MVC历史演变
JSP表示层的两种架构模式:
- Model 1架构模式(JSP+JavaBean)
- Model 2架构模式(JSP+Sevlet+JavaBean)
Model1
在model1中,JavaBean由jsp页面创建;
Model2
Model 2是基于MVC架构的设计模式。
在Model 2架构中,Servlet作为前端控制器,负责接收客户端发送的请求;
在Servlet中只包含控制逻辑和简单的前端处理;
后端JavaBean来完成实际的逻辑处理;最后,转发到相应的JSP页面处理显示逻辑。
- request周期的javabean:
- session周期的javaBean:
- application周期的JavaBean:
一些通俗理解图示:
实际流程:
5.2 MVC模式与应用程序分层的区别
MVC模式是一种软件架构方式,而应用程序分层这是一种代码组织方式。MVC模式与应用程序分层的目标都是一致的:为了解耦和、提高代码复用性。
致谢&部分资源出处:百战程序员、B站@DT课堂-颜群的JAVA课、菜鸟教程