Bootstrap

【JavaWeb】JSP简介

一、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”

  1. <%! %> 定义方法-全局变量;
  2. <% %> 存储java语句-局部变量;
  3. <%= %> 输出表达式;

要点

  • 修改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对象

请求对象:存储“客户端”向服务器发送的请求信息;

请求报文结构

示意图

作用

  1. 取得请求参数的值;
  2. 操作request范围的属性;
  3. 执行include指令或forward指令。

常见方法:

  • request获取请求参数的值

最好是先设置好解码方式(应与发送请求的页面的编码方式相同);

3.1.1 请求转发

请求转发是服务端的一种请求方式,相当于在服务端中直接请求某个资源。

RequestDispatcher dispatcher = request.getRequestDispatcher("/test.jsp");
dispatcher.forward(request,response);

简写方式:

request.getRequestDispatcher("/test.jsp").forword(request,response);

请求转发与重定向的区别

  1. 请求转发对于客户端浏览器而言是在一次请求与响应中完成的,而重定向是在两次请求和响应中完成的;
  2. 请求转发并不会改变客户端浏览器地址栏中的内容;而重定向会改变客户端浏览器地址栏中内容;
  3. 请求转发可以通过使用request对象进行数据传递(request.setAttribute("key"));而重定向不能;
  4. 如果是处理DML操作,建议使用重定向方式为客户端浏览器产生响应,可以解决表单重复提交的现象;

请求转发

重定向

地址栏是否改变

不变

改变

是否保留第一次请求的数据

保留

不保留

客户端请求及响应的次数

1

2

跳转发生的位置

服务端

客户端发出的第二次跳转

案例1:请求转发

需求:在Servlet中获取客户端浏览器所支持的语言,并通过JSP页面将客户端浏览器所支持的语言响应给客户端浏览器。

思路:创建一个Servlet用于获取请求中的Accept-Language头部信息,将其存入request对象中,通过请求转发的方式传给showMsg.jsp进行美化输出;

  1. 创建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);
    }
}

  1. 创建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>
  1. 测试

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去匹配,匹配成功则说明不是第一次访问;

Session详解,学习Session,这篇文章就够了(包含底层分析和使用)_秃头披风侠.的博客-CSDN博客什么是sessionsession在网络应用中称为“会话控制”,是服务器为了保存用户状态而创建的一个特殊的对象。简而言之,session就是一个对象,用于存储信息。session有什么用 我们先来想一个问题,这个问题就是我们在游览购物网站时,我们并没有登录,但是我们任然可以将商品加入购物车,并且进行查看,当我们退出游览器后再打开游览器进行查看,购物车中依然有我们选择的商品,这该怎么实现呢? 当然,我们可以使用cookie,但是cookie能..._sessionhttps://blog.csdn.net/m0_51545690/article/details/123384986

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" %>

标签

描述

<c:out>

用于在JSP中显示数据,就像<%= ... >

<c:set>

用于保存数据

<c:remove>

用于删除数据

<c:catch>

用来处理产生错误的异常状况,并且将错误信息储存起来

<c:if>

与我们在一般程序中用的if一样

<c:choose>

本身只当做<c:when>和<c:otherwise>的父标签

<c:when>

<c:choose>的子标签,用来判断条件是否成立

<c:otherwise>

<c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行

<c:import>

检索一个绝对或相对 URL,然后将其内容暴露给页面

<c:forEach>

基础迭代标签,接受多种集合类型

<c:forTokens>

根据指定的分隔符来分隔内容并迭代输出

<c:param>

用来给包含或重定向的页面传递参数

<c:redirect>

重定向至一个新的URL.

<c:url>

使用可选的查询参数来创造一个URL

格式化标签:JSTL格式化标签用来格式化并输出文本、日期、时间、数字。

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

标签

描述

<fmt:formatNumber>

使用指定的格式或精度格式化数字

<fmt:parseNumber>

解析一个代表着数字,货币或百分比的字符串

<fmt:formatDate>

使用指定的风格或模式格式化日期和时间

<fmt:parseDate>

解析一个代表着日期或时间的字符串

<fmt:bundle>

绑定资源

<fmt:setLocale>

指定地区

<fmt:setBundle>

绑定资源

<fmt:timeZone>

指定时区

<fmt:setTimeZone>

指定时区

<fmt:message>

显示资源配置文件信息

<fmt:requestEncoding>

设置request的字符编码

sql标签:JSTL SQL标签库提供了与关系型数据库(Oracle,MySQL,SQL Server等等)进行交互的标签。

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

标签

描述

<sql:setDataSource>

指定数据源

<sql:query>

运行SQL查询语句

<sql:update>

运行SQL更新语句

<sql:param>

将SQL语句中的参数设为指定值

<sql:dateParam>

将SQL语句中的日期参数设为指定的java.util.Date 对象值

<sql:transaction>

在共享数据库连接中提供嵌套的数据库行为元素,将所有语句以一个事务的形式来运行

xml标签:JSTL XML标签库提供了创建和操作XML文档的标签。

<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

在使用xml标签前,你必须将XML 和 XPath 的相关包拷贝至你的<Tomcat 安装目录>\lib下:

标签

描述

<x:out>

与<%= ... >,类似,不过只用于XPath表达式

<x:parse>

解析 XML 数据

<x:set>

设置XPath表达式

<x:if>

判断XPath表达式,若为真,则执行本体中的内容,否则跳过本体

<x:forEach>

迭代XML文档中的节点

<x:choose>

<x:when>和<x:otherwise>的父标签

<x:when>

<x:choose>的子标签,用来进行条件判断

<x:otherwise>

<x:choose>的子标签,当<x:when>判断为false时被执行

<x:transform>

将XSL转换应用在XML文档中

<x:param>

与<x:transform>共同使用,用于设置XSL样式表

JSTL函数:JSTL包含一系列标准函数,大部分是通用的字符串处理函数;

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

函数

描述

fn:contains()

测试输入的字符串是否包含指定的子串

fn:containsIgnoreCase()

测试输入的字符串是否包含指定的子串,大小写不敏感

fn:endsWith()

测试输入的字符串是否以指定的后缀结尾

fn:escapeXml()

跳过可以作为XML标记的字符

fn:indexOf()

返回指定字符串在输入字符串中出现的位置

fn:join()

将数组中的元素合成一个字符串然后输出

fn:length()

返回字符串长度

fn:replace()

将输入字符串中指定的位置替换为指定的字符串然后返回

fn:split()

将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回

fn:startsWith()

测试输入字符串是否以指定的前缀开始

fn:substring()

返回字符串的子集

fn:substringAfter()

返回字符串在指定子串之后的子集

fn:substringBefore()

返回字符串在指定子串之前的子集

fn:toLowerCase()

将字符串中的字符转为小写

fn:toUpperCase()

将字符串中的字符转为大写

fn:trim()

移除首尾的空白符

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

分析

  1. 多个when都满足时,会选取第一个匹配到的when进行执行;
  2. 没有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

需求

  1. 创建Users对象,含有userid,username属性;
  2. 创建一个Servlet,在Servlet中创建多个Users对象并放到List集合中,在showUsers.jsp的页面中显示所有的Users对象的信息;

实现

  1. 创建类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;
    }
}
  1. 创建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);
    }
}
  1. 创建视图层界面,获取请求中的数据并美化输出:
<%@ 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>
  1. 测试结果

案例2:使用<c:foreach>标签迭代Map

需求

  1. 创建Users对象,含有userid,username属性;
  2. 创建一个Servlet,在Servlet中创建多个Users对象并放到Map集合中,在showUsers2.jsp的页面中显示所有的Users对象的信息;

实现

  1. 创建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);
    }
}
  1. 创建视图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>
  1. 测试结果

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课、菜鸟教程

;