Java学习笔记-Day56 MVC模式、EL和JSTL



一、MVC模式


MVC(Model-View-Controller)是一种软件架构设计模式,MVC模式将软件的代码按照模型(M)、视图(V)、控制器(C)三部分组织。
在这里插入图片描述
使用MVC模式构建应用,具有以下优势:

  • 耦合性低:视图层和业务层分离,耦合性降低,可以独立修改。
  • 重用性高:可以用不同的视图访问模型部分,实现在不同终端上访问应用。
  • 可维护性高:视图与业务分离,降低了维护成本。

MVC模式中有三个角色,分别是M模型,V视图,C控制器。使用不同的编程语言都可以实现MVC模式。

M指的是模型,实现业务逻辑。V指的是视图,实现显示页面。C指的是控制器,实现控制逻辑,接收视图的请求,调用业务逻辑处理,并跳转到不同的视图显示处理结果。在JavaEE中,M模型为Java类( Service、Bean(数据传递载体,实体类)、Dao),V视图为html和jsp,C控制器为Servlet。

在控制器和视图之间,常常需要共享数据。例如从数据查出来的商品列表信息,需要从控制器发送到视图。

Servlet和JSP之间共享数据一般使用请求、会话、上下文范围的属性进行。HttpServletRequest、HttpSession、ServletContext接口中都定义了存取、查询、删除属性的方法。使用原则:尽量用范围小的属性,即请求范围内共享就用请求,以此类推。否则会造成资源浪费,降低安全性。

MVC模式中,控制器和视图之间需要进行跳转,Servlet规范中,有三种跳转方式:

  1. redirect:调用响应接口的sendRedirect方法,响应重定向,相当于重新请求新的资源,当前请求对象不会到目标资源;
  2. forward: 调用请求转发器接口的forward方法,请求转发,将当前的请求、响应对象转发到目标资源;
  3. include:调用请求转发器接口的include方法,动态包含,将目标资源的请求、响应对象包含到当前资源;

二、EL和JSTL

1、EL

1.1、EL简介


EL是Expression Language的简称,即表达式语言。EL在JSP中使用,服务器会对其进行解析翻译,生成相应的Java代码。EL的作用是用来在JSP页面输出动态内容,可以替代JSP中的表达式元素 <%=%>。使用EL只是让JSP编写起来更为简单。

EL的一般格式如下:以 ${ 开始,以 } 结束, ${EL表达式}

${param.username} 等同于 <%=request.getParameter(“username”)%>

1.2、内置对象


为了能够方便地输出数据,EL提供了11个内置对象:

  • 2个内置对象为了方便输出请求参数: param、paramValues
  • 4个内置对象为了方便输出各个范围的属性: pageScope、requestScope、sessionScope、applicationScope
  • 2个与请求头有关的内置对象:header、headerValues
  • 2个其他内置对象:cookie、initParam
  • 1个特殊的内置对象:pageContext
隐式对象 描述
pageScope 来自页面范围的范围变量
requestScope 来自请求范围的范围变量
sessionScope 会话范围的范围变量
applicationScope 应用范围的范围变量
param 请求参数作为字符串
paramValues 请求参数作为字符串集合
header HTTP请求标头作为字符串
headerValues HTTP请求标头作为字符串集合
initParam 上下文初始化参数
cookie Cookie值
pageContext 当前页面的JSP PageContext对象

1.2.1、内置对象param


内置对象param:用来输出请求参数的值,格式为${param.请求参数名字}

使用表达式:<%=request.getParameter(“name”)%>
使用EL:${param.name}

1.2.2、内置对象paramValues


内置对象paramValues:用来获取一对多的参数值,返回一个数组。比如某请求参数是通过checkbox传递的,名字为hobbies,要输出所有hobbies值中的第一个值,可以使用如下两种方式:

使用表达式:<%=request.getParameterValues(“hobbies”)[0]%>
使用EL:${paramValues.hobbies[0]}

1.2.3、内置对象header


内置对象header:用来输出某一个请求头的值,格式为${header.请求头名字},例如输出请求头accept的值

${header.accept}

1.2.4、内置对象headerValues


内置对象headerValues:如果某个请求头的值有多个,则使用headerValues返回一个数组。如下代码所示:

${headerValues.cookie[0]}
上述代码将返回请求头cookie中的第一个值,例如:JSESSIONID=A6A22CA4AEE8F9E1111422C889740B24:

1.2.5、内置对象cookie


内置对象cookie:用来获取cookie的值,如下代码所示,将输出名字为JSESSIONID的cookie的值: JSESSIONID=A6A22CA4AEE8F9E1111422C889740B24:

${cookie.JSESSIONID.value}

1.2.6、内置对象initParam


内置对象initParam:用来输出上下文参数

在web.xml中配置上下文参数:
<context-param>
   <param-name>path</param-name>
   <param-value>/WEB-INF/props</param-value>
</context-param>
在JSP中使用EL输出path的值:
${initParam.path}

1.2.7、内置对象pageContext


内置对象pageContext:EL中的pageContext对象可以调用PageContext类中所有符合规范的getXxx方法,如PageContext类中有如下方法:public abstract ServletRequest getRequest(), 可以通过如下EL调用该方法:

${pageContext.request}

该方法将输出请求对象:org.apache.catalina.core.ApplicationHttpRequest@1b98cbb
既然该EL返回的是真正的请求对象,那么就可以继续调用HttpServletRequest中的其他getXxx方法,如:

${pageContext.request.remoteAddr}
上述表达式将调用请求中的getRemoteAddr方法,输出其返回值,例如:127.0.0.1

1.2.8、获取属性数据有关的内置对象


与获取属性数据有关的内置对象有四个,分别是:

  • pageScope:页面范围
  • requestScope:请求范围
  • sessionScope:会话范围
  • applicationScope:上下文范围

例如获得名字为user的请求属性的pwd属性值,EL为:${requestScope.user.pwd}
等同于 <%=((User)request.getAttribute(“user")).getPwd()%>

检索顺序:当不指定范围时,例如,${user.pwd},将自动从pageScope开始查找,直到applicationScope,如果没查到,则什么也不显示

pageScope作用域:与页面作用域(page)中的属性相关联的Map类,主要用于获取页面范围内的属性值。

requestScope作用域:与请求作用域(request)中的属性相关联的Map类,主要用于获取请求范围内的属性值。

sessionScope作用域:与会话作用域(session)中的属性相关联的Map类,主要用于获取会话范围内的属性值。

applicationScope作用域:与应用程序作用域(application)中的属性相关联的Map类,主要用于获取应用程序范围内的属性值。

默认的访问顺序:pageScope→requestScope→sessionScope→applicationScope

作用域 Java代码取值 EL取值
请求作用域 request.getAttribute(“goods”); ${ requestScope.goods }
会话作用域 session.getAttribute(“username”); ${ sessionScope.username }
程序作用域 application.getAttribute(“user”); ${ applicationScope.user }
页面作用域 pageContext.getAttribute(“pageNum”); ${ pageScope.pageNum }

使用pageScope/requestScope/sessionScope/applicationScope中的某一个内置对象获取属性时,则是强制使用该作用域的属性。

页面范围user对象的pwd属性:${pageScope.user.pwd}
请求范围user对象的pwd属性:${requestScope.user.pwd}
会话范围user对象的pwd属性:${sessionScope.user.pwd}
上下文范围user对象的pwd属性:${applicationScope.user.pwd}

1.3、EL运算符


EL算术运算符:+ 实现加法运算、- 实现减法运算、* 实现乘法运算、/或div实现除法运算、%或mod实现求模运算。

EL比较运算符:有6种比较运算符,可以对值进行比较,返回值为true或fasle。

  • ==eq 表示等于
  • !=ne 表示不等于
  • <lt 表示小于
  • >gt 表示大于
  • <=le 表示小于等于
  • >=ge 表示大于等于

EL逻辑运算符:EL中提供了3个逻辑运算符,可以对boolean类型的值进行运算,返回值为true或false。

  • &&and表示交集,两个值都是true才返回true。
  • ||or表示并集,两个值只要有一个是true,即返回true。
  • !not表示非

使用[]指定索引的方式可以获取数组或List中的元素;

返回请求范围内商品列表集合的第一个商品的名称:${requestScope.productsList[0].productName}

EL其他运算符:除了算术、比较、逻辑运算符外,还有三种其他运算符。

  • empty运算符:判断值是否为null,如果是null,返回true,否则返回false。
  • 关系运算符:${A?B:C} 如果A为true,则执行B,如果A为false,则执行C。
  • ()运算符:通过()可改变优先级

2、JSTL

2.1、JSTL简介


JSP中的静态内容都使用HTML标签实现,如果动态内容也能够使用标签实现,将大大简化JSP。JSP中的标签库就是用Java类 ( 遵守一定规范,成为标签处理器类 ) 实现动态功能,将这些动态功能在tld文件 ( taglib description 标签库描述文件 ) 中描述为标签,在JSP中通过使用标签就可以实现动态功能,不用在JSP中编写复杂的Java代码。

标签库由 标签处理器类 和 描述文件tld文件组成。其作用:简化JSP文件,不需在JSP中写大量的Java脚本。标签可以重复使用,利于维护。

JSTL是一套定义好的标签库,可以直接使用。JSTL的全称是Jsp Standard Tag Library,即JSP标准标签库。JSTL包含很多标签,根据其作用可以分为:属性相关的标签、条件分支相关的标签、迭代标签、其他标签。

在这里插入图片描述
要使用JSTL,首先要把JSTL相关的资源文件保存到lib目录下,使用解压缩软件解压jar文件,主要包含两类内容:

在这里插入图片描述
tld文件中,对标签进行了描述,包括标签的名字,标签处理器类,标签的属性等,同时一个tld文件有一个唯一标记的uri。

2.2、JSTL标签库的使用


(1)将JSTL相关的两个jar文件保存到 WebContent/WEN-INF/lib 目录下。

(2)在JSP中使用taglib指令引入标签库。

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

uri是tld文件的唯一标记;需要查看tld文件获得。prefix指定使用该标签库时的前缀,只要不使用保留字,其他字符均可。不过一般如果使用c.tld标签库,前缀就用c,可增强可读性。

JSTL中与属性操作有关的标签有如下两个:

标签名字 所在标签库 作用 属性
set c.tld 在指定范围内,将对象保存为属性; var:属性名字
scope:属性范围
value:属性值,可以使用EL
remove c.tld 在指定范围内,删除属性; var:属性名字
scope:属性范围
<!--设置-->
<c:set var="path" scope="page" value="${pageContext.request.contextPath}"></c:set>
<!--使用-->
${path}


JSTL中与条件分支有关的标签有如下四个:

标签名字 所在标签库 作用 属性
if c.tld 实现if逻辑,当条件为true,执行标签体内容; test:返回值为布尔值的表达式,作为分支的条件;
choose c.tld 实现if/else if/else逻辑,需要与when,otherwise结合使用
when c.tld 实现else if逻辑,与choose、otherwise配合使用; test:返回值为布尔值的表达式,作为分支的条件;
otherwise c.tld 实现else逻辑,与 choose、when配合使用;
<c:set var = "name" value = "Tom"/>
<c:if test= "${not empty name}">
	<c:out value = "${name}"/>
</c:if>
<c:set var ="IDE" value= "Eclipse"/>
<c:choose>
	<c:when test = "${IDE == 'IDEA' }">
		<c:out value = "使用的工具是IDEA"/>
	</c:when>
	<c:when test = "${IDE == 'Eclipse' }">
		<c:out value = "使用的工具是Eclipse"/>
	</c:when>
	<c:when test = "${IDE == 'MyEclipse' }">
		<c:out value = "使用的工具是MyEclipse"/>
	</c:when>
	<c:otherwise>
   			<c:out value = "用记事本写代码!"/>
   	</c:otherwise>
</c:choose>

JSTL中与迭代有关的标签如下所示

标签名字 所在标签库 作用 属性
forEach c.tld 迭代集合或数组; items:需要迭代的数组或集合对象,可以使用EL表达式;
var:迭代过程中的临时变量,存储在PageScope中;
forToken c.tld 迭代字符串; items:指定需要迭代的字符串;
delims:表示分隔符;
var:表示使用分隔符分割items产生的字符串;
<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<!-- 加入taglib标记 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
<style type="text/css">
td {
     
     
	border: 1px solid black;
}

#tab {
     
     
	width: 600px;
	text-align: center;
}
</style>
<link href="${pagecontext.request.contextPath}/bootstrap-3.3.7/css/bootstrap.css">
</head>

<body>
	<div id="div1">
		<table id="tab" border="1" cellspacing="0" cellpadding="20">
			<thead>
				<tr>
					<th>编号</th>
					<th>名字</th>
					<th>密码</th>
					<th>年龄</th>
					<th>性别</th>
				</tr>
			</thead>
			<tbody>
				<c:forEach items="${requestScope.list}" var="u">
					<tr>
						<td>${u.userid}</td>
						<td>${u.uname}</td>
						<td>${u.upwd}</td>
						<td>${u.uage}</td>
						<td>${u.usex==1?"男":"女"}</td>
					</tr>
				</c:forEach>
			</tbody>
		</table>
	</div>
	<script src="${pageContext.request.contextPath}/js/jquery-2.0.3.js"></script>
	<script
		src="${pageContext.request.contextPath}/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_42141141/article/details/111709913
今日推荐