欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jsp

程序员文章站 2022-07-15 07:59:04
...

JSP

jsp的介绍

JSP:Java Server Page SUN 公司提供的动态网页编程技术,是 Java Web 服务器端的动态资源。 它相比 html 而言,html 只能为用户提供静态数据,而 Jsp 技术允许在页面中嵌套 java 代码,为 用户提供动态数据。

相比 servlet 而言,servlet 很难对数据进行排版,而 jsp 除了可以用 java 代码产生动态数据的同 时,也很容易对数据进行排版。

不管是 JSP 还是 Servlet,虽然都可以用于开发动态 web 资源。但由于这 2 门技术各自的特点,在 长期的软件实践中,人们逐渐把 servlet 作为 web 应用中的控制器组件来使用, 而把 JSP 技术作为数据 显示模板来使用。

其实 Jsp 就是一个 Servlet,当我们第一次访问 Jsp 的时候,Jsp 引擎都会将这个 Jsp 翻译成一个 Servlet,这个文件存放在 Tomcat 中的 work 目录中。

基础语法

注释

在 JSP 中支持两种注释的语法操作,一种是显示注释,这种注释是允许客户端看见的;另一种是隐 式注释,此种注释是客户端无法看见的

① 显示注释语法:从 HTML 风格继承而来

② 隐式注释语法:从 JAVA 风格继承;JSP 自己的注释

JSP 的三种注释方式:

1)// 注释,单行注释 /* 多行注释 */ (在jsp生成的.java文件中可见)

2) (在浏览器解析的html中可见)

3)<%-- JSP 注释 --%> (只在jsp中可见)

Scriptlet

在 JSP 中最重要的部分就是 Scriptlet(脚本小程序),所有嵌入在 HTML 代码中的 Java 程序都必 须使用 Scriptlet 标记出来,在 JSP 中一共有三种 Scriptlet 代码:

第一种:<% %> :java 脚本段,可以定义局部变量、编写语句

第二种:<%! %>:声明,可以定义全局(成员)变量、方法、类

第三种:<%= %>:表达式,数据、一个变量或具体内容

通过观察解析为 java 文件的 jsp 代码理解三种小脚本

jsp的指令标签

JSP 的指令标签用来控制整个 jsp 的行为,就当前 JSP 页面的某些方面对 JSP 转换器作出指示,可 以用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。

<%@ page language = “java” contentType=“text/html;Charset=UTF-8” Encoding=“UTF-8”%>

<%@ page import=“需要导入的jar包” %>

page指令

language属性,用来指定语言,一般是java

contentType 和 pageEncoding,分别用来指定 MIME 类型和编码格式。

import 属性,用来引入其他包,和 java 中 import 语句作用相同。

MIME 类型

<%@ page contentType=”text/html;charset=UTF-8”%>

写成<%@ page contentType=”test/html;charset=UTF-8”%> 此时则变成下载

文件字符编码

contentType 主要的功能是用来设置 MIME(页面响应类型),而 charset=”UTF-8” 指定了编码,利用 pageEncoding =”UTF-8”也能指定编码,前者更常用。

在 JSP 中,如果 charset 存在,那么 JSP 的编码由 charset 决定,而如果不存在才会由

pageEncoding 来决定,如果都不存在,则使用 ISO-8859-1 编码。

import导包

page 指令中存在 import 属性,所以导包就可以正确使用了,在整个 page 指令的属性中, 只有

import 语句可以多次出现,其他属性都只能设置一次。 能导包意味着可以直接在 jsp 中链接数据库。

<%@ page import=“java.util." import="java.io.”%>多个import可以通过,分隔

<%@page import=“java.util.* ,java.io.*” %>

include静态包含

<%@ include file=“include.jsp”%>(可以是html也可以是jsp页面)

静态包含就是将内容进行直接替换,就好比程序中定义的变量一样是在 servlet 引擎转译时, 就把此文件内容包含了进去(两个文件的源代码整合到一起,全部放到_jspService 方法中),所以只 生成了一个 servlet,所以两个页面不能有同名的变量。运行效率高一点点。耦合性较高,不够灵活。

taglib导入标签库

<%@ tagilb uri=“http://java.sun.com/jsp/jstl/core” prefix=“c” %>

jsp的动作标签

动作标签,它们被编译成执行某个操作的 Java 代码,例如访问某个 Java 对象,或者调用某个方 法。JSP 容器有自己支持的标准动作。除标准动作之外,还可以创建指定的标签,用来执行某些操作。 这些 jsp 的动作标签,与 html 提供的标签有本质的区别: 动作标签是由 tomcat(服务器)来解释执行!与 java 代码一样,都是在服务器端执行 html 由浏览器来执行!

include

include 动作用于动态地包含另一个资源,它可以包含另一个 JSP 页面、 Servlet 或者一个静态的 HTML 页面。

使用包含操作,可以将一些重复的代码包含进来继续使用,从正常的页面组成来看,有时可能分为 几个区域。而其中的一些区域可能是一直不需要改变的,改变的就其中的一个具体内容区域。现在有两 种方法可以实现上述功能。

方法一:在每个 JSP 页面(HTML)都包含工具栏、头部信息、尾部信息、具体内容。

方法二:将工具栏、头部信息、尾部信息都分成各个独立的文件,以后使用的时候直接导入进来。

很明显,第二种方法比第一种更好,第一种会存在很多重复的代码,并且修改很不方便,在 JSP 中 如果要想实现包含的操作,有两种做法:静态包含、动态包含。

静态包含见上面:

动态包含

动态包含在代码的编译阶段,包含和被包含部分是两个独立的部分,只有当页面被请求的时候时, 才会动态包含进来,好比方法的调用。

<jsp:include page="include.html|include.jsp"></jsp:include>

<% String t="include.jsp|include.html" %>
<jsp:include page="<%=t%>"></jsp:include> 

注意:动态包含,中间不要加任何内容,包括空格,除非确认要使用参数,否则报错!

使用动态包含还可以通过在页面之间传参。接收参数通过 request.getParameter(name) 来完成。

<jsp:include page="include.jsp"> 
	<jsp:param value="zhangsan" name="username"/> 
</jsp:include> 
<%=request.getParameter("uername"); %>
forward

forward 动作用于请求转发,可以将一个用户的请求(request),从一个页面传递到另一个页面,跳转的语法:

<!-- 不传参数 --> 
<jsp:forward page="要转到的资源路径|<%=表达式%>">
</jsp:forward> 
<!-- 传参数 --> 
<jsp:forward page="要转到的资源路径|<%=表达式%>"> 
	<jsp:param value="参数内容" name="参数名称"/> 
</jsp:forward>

jsp 的 forward 动作标签,其作用的理解可以等价于 Servlet 域对象 HttpServletRequest 的请求转 发,即 request.getRequestDispatcher(“要转到的资源路径”).forward(request, response);

useBean

useBean 动作用来装载一个将在 JSP 页面中使用的 JavaBean。相当于创建了一个 JavaBean 对 象,但是还没有进行属性设置,属性的设置和获取可以通过 jsp:setProperty 和 jsp:getProperty 动作标 签来完成。

<jsp:useBean id="user" class="com.pojo.User">
	<!-- 
		相当于
		User user =new User();
	 -->
</jsp:useBean>
属性 描述
id 指定Bean的别名
class 指定Bean的完整包名。
type 指定将引用该对象变量的类型。
beanName 通过 java.beans.Beans 的 instantiate() 方法指定Bean的名字。
setProperty

setProperty 动作用来设置已经实例化的 Bean 对象的属性,可以使用如下两种方式。

①在< jsp:useBean>< /jsp:useBean> 后使用 <jsp:setProperty />

<jsp:useBean id="user" class="com.pojo.User"></jsp:useBean>
<jsp:setProperty property="username" name="user" value="zs"/>

②<jsp:setProperty /> 出现在 < jsp:useBean>< /jsp:useBean> 标签内

<jsp:useBean id="user2" class="com.pojo.User">
	<jsp:setProperty property="username" name="user2" value="ls"/>
</jsp:useBean>

注意

<jsp:setProperty /> 中的 name 值要与 < jsp:useBean> 中的 id 值相同

< jsp:useBean>里面的代码,初始化的时候执行一次

getProperty
<jsp:useBean id="user3" class="com.pojo.User">
	<jsp:setProperty property="username" name="user3" value="zs"/>
	<jsp:getProperty property="username" name="user3"/>
</jsp:useBean>

注意

1、在使用 <jsp:getProperty /> 之前,必须使用 < jsp:useBean>< /jsp:useBean> 创建该对象,若没有进行赋值则为 null;若不创建,则会 500 报错。

2、setter 和 getter 存在且符合规范

el表达式、

el语法

EL(Expression Language)是为了使 JSP 写起来更加简单。表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法,让 Jsp 的代码更加简化。

语法结构非常简单:${expression}

EL 表达式一般操作的都是域对象中的数据,操作不了局部变量。域对象的概念在 JSP 中一共有四 个pageContext, request, session, application;范围依次是,本页面,一次请求,一次会话,整个 应用程序。而 EL 默认的查找方式为从小到大查找,找到即可。当域对象全找完了还未找到则返回空字 符串””。

当需要指定从某个特定的域对象中查找数据时可以使用 el 表达式的隐含对象,分别是: pageScope, requestScope, sessionScope, applicationScope。

el运算

使用 EL 表达式可以用来判断集合中是否有元素 ${empty col}

  1. List 遍历

${list[0]}

  1. 访问 map

map[&quot;key&quot;]{map[&quot;key&quot;]} 或{map.key}

  1. 做+、-、*、/(也可以使用 div 来表示)、%、==

jsp内置对象

九大内置对象

内置对象 类型 描述
pageContext javax.servlet.jsp.PageContext jsp的页面的容器
request javax.servlet.http.HttpServletRequest 得到用户的请求
response javax.servlet.http.HttpServletResponse 服务器向客户端的回应消息
session javax.servlet.http.HttpSession 用来保存每一个用户的信息
application javax.servlet.ServletContext 表示所有用户的共享信息
config javax.servlet.ServletConfig 服务器配置,可以获取初始化参数
out javax.servlet.jsp.JspWriter 页面输出
page java.lang.Object 表示该页面的一个serlvet实例
exception java.lang.Throwable 表示jsp页面发生的异常,在错误页面才有用

四种属性范围:

page(pageContext):只在一个页面中保存属性。 跳转之后无效。
request:只在一次请求中有效,服务器跳转之后有效。 客户端跳转无效
session:在一次会话中有效。服务器跳转、客户端跳转都有效。 网页关闭重新打开无效
application:在整个服务器上保存,所有用户都可使用。 重启服务器后无效
注意:如果设置过多的application属性范围会影响服务器性能。

域对象具备的方法:

方法 描述
setAttribute(String name,Object value) 设置属性的名称及内容
getAttribute(String name) 根据属性名称取得属性
removeAttribute(String name) 删除指定名称的属性

page范围:

page 范围是通过 pageContext 对象设置的,之前研究过的 page 属性范围中使用的是 pageContext 进行属性设置的,但是从 javax.servlet.jsp.PageContext 类中可以发现,有以下的一种设 置属性的方法:

public void setAttribute(String name, Object value, int scope)

在 PageContext 类中存在四个表示属性范围的常量,可以直接通过这些常量指定 scope:

pageContext.PAGE_SCOPE

pageContext.REQUEST_SCOPE

pageContext.SESSION_SCOPE

pageContext.APPLICATION_SCOPE

pageContext.setAttribute(“name”, “zhangsan”, pageContext.APPLICATION_SCOPE);

在其他页面取值时,需要指定对应的作用域,或者使用el表达式(使用el表达式,会优先从最近的作用域开始寻找匹配的值,没找到返回一个空串)

jstl标签

jstl简介

Java Server Pages Standard Tag Libray(JSTL):JSP 标准标签库,是一个定制标签类库的集合,用 于解决一些常见的问题,例如迭代一个映射或者集合、条件测试、XML 处理,甚至数据库和访问数据库 操作等。

我们现在只讨论 JSTL 中最重要的标签,条件动作、迭代集合以及格式化数字和日期几个标签。

核心标签库:http://java.sun.com/jsp/jstl/core 包含 Web 应用的常见工作,比如:循环、表达式 值、基本输入输出等。

格式化标签库:http://java.sun.com/jsp/jstl/fmt 用来格式化显示数据的工作,比如:对不同区域 的日期格式化等。

为了在 JSP 页面使用 JSTL 类库,必须以下列格式使用 taglib 指令:

<%@taglib uri=”” prefifix=””%>

例如:<%@taglib uri=”http://java.sun.com/jsp/jstl/core” prefifix=”c”%>

​ <%@taglib uri=”http://java.sun.com/jsp/jstl/fmt” prefifix=”fmt”%>

前缀可以是任意内容,遵循规范可以使团队中由不同人员编写的代码更加相似;所以,建议使用事 先设计好的前缀。此时需要导入两个 jar 包:jstl.jar和standard.jar。

标签的使用

条件动作标签
if标签

if 标签先对某个条件进行测试,如果该条件运算结果为 true,则处理它的主体内容,测试结果保存在一个 Boolean 对象中,并创建一个限域变量来引用 Boolean 对象。可以利用 var 属性设置限域变量名,利用scope 属性来指定其作用范围。

if 的语法有两种形式:没有主体内容、有主体内容.

没有主体内容

<!--<c:if test="条件" var="用于存储条件结果的变量" scope="var属性的作用域,默认page"> </c:if> --> <%request.setAttribute("num", "1"); %>
<c:if test="${'1==1'}" var="flag"></c:if> <!-- flase --> 
<c:if test="1==1" var="flag"></c:if> <!-- flase --> 
<c:if test="${'num==1'}" var="flag"></c:if> <!-- true --> 
<c:if test="${1==1}" var="flag"></c:if> <!-- true -->

该情况下:var 指定的限域变量由同一个 JSP 页面中后面的标签测试所决定。

有主体内容

<%
	int num = 66;
	request.setAttribute("num",66);
%>
<c:if test="${num>60&&num<=70}">
	还行
</c:if>
<c:if test="${num>70&&num<=80}">
	不错
</c:if>
choose、when、otherwise

choose 和 when 标签的作用与 Java 中的 switch 和 case 关键字相似。也就是说:他们为相互排斥 的条件式执行提供相关内容。choose 标签内容部必须嵌有一个或多个 when 标签,每个 when 标签代 表可以进行运算和处理的一种情况。otherwise 标签用于默认的条件代码块,如果所有的 when 标签的 测试条件运算结果都不为true ,就会执行该代码块。如果有 otherwise标签,它必须放在最后一个when标签之后,否则会报错。choose 和otherwise 标签没有属性,when标签则必须使用 test 属性设定一个条件,用于确定是 否处理主体内容。

<%
	int num = 66;
	request.setAttribute("num",66);
%>
<c:choose>
	<c:when test="${num<=60}">
		<h1>你还差得远呢!</h1>
	</c:when>
	<c:when test="${num<=80}">
		<h1>还行!</h1>
	</c:when>
	<c:otherwise>
		<h1>牛批!</h1>
	</c:otherwise>
</c:choose>

注意:

1、choose标签中只能有when和otherwise标签,when和otherwise标签中可有其他标签

2、choose中至少有一个when标签

3、choose标签和otherwise标签没有属性,when标签必须要有test属性

4、otherwise标签必须放在最后一个when标签之后

5、当所有的when标签的条件都不成立时,才执行otherwise标签中的语句

迭代标签
forEach

forEach 是将一个主体内容迭代多次,或者迭代一个对象集合。可以迭代的对象包括所有的 java.util.Collection 和 java.util.Map 接口的实现,以及对象或者基本类型的数组。他还可以迭代 java.util.Iterator 和 java.util. Enumeration,但不能在多个动作指令中使用 Iterator 或者 Enumeration,因为 Iterator 或者 Enumeration 都不能重置(reset)。

<% 
	List<User> list = new ArrayList<>();
	User user1 = new User("张三","123456",18,1);
	User user2 = new User("李四","122356",15,0);
	User user3 = new User("王五","121256",27,0);
	User user4 = new User("赵六","123312",33,1);
	list.add(user1);
	list.add(user2);
	list.add(user3);
	list.add(user4);
	request.setAttribute("list",list);
%>

<% 
	Map<String,Object> map = new HashMap<>();
	map.put("u1", user1);
	map.put("u2", user2);
	map.put("u3", user3);
	map.put("u4", user4);
	request.setAttribute("map",map);
%>

<!-- 
	var 存放现在指向的成员,(每次迭代结束会覆盖之前的成员) 
	items 被迭代的集合对象
--> 
<c:forEach var="user" items="${requestScope.list}">
	<h1>${user.username}</h1>
	<h2>${user.pwd}</h2>
	<h3>${user.age}</h3>
	<h4>
	<c:if test="${user.gender==0}">女</c:if>
	<c:if test="${user.gender==1}">男</c:if>
	</h4>
	<h4>${user.gender}</h4>
</c:forEach>
<hr>

<!-- 
	begin设置开始的位置,end设置结束的位置 step设置每次迭代的间隔数(默认为1)
	varStatus 属性的使用:用来存放现在指向的相关成员信息
	属性   类型      描述
	index number 现在指到成员的索引
	count number 总共指到成员的总数
	first boolean 现在指到的成员是否为第一个成员
	last boolean 现在指到的成员是否为最后一个成员
-->
<c:forEach var="user" items="${requestScope.map}" begin="0" end="9" varStatus="userStr">
	<h1>${user.value["username"]} ${userStr.index}</h1>
	<h2>${user.value.pwd} ${userStr.count}</h2>
	<h3>${user.value.age} ${userStr.first}</h3>
	<h4>
	<c:if test="${user.value.gender==0}">女</c:if>
	<c:if test="${user.value.gender==1}">男</c:if>
	</h4>
	<h4>${user.value.gender} ${userStr.last}</h4>
</c:forEach>
<hr>
<c:forEach var="i" begin="1" end="10" step="2">
	<h3>${i}</h3>
</c:forEach>
格式化标签

这里只介绍常用的几种属性

formatNumber

该标签用指定的格式或精度来格式化数字

<!-- 无主体,值放在value属性中,有主体不需要value -->
<fmt:formatNumber value="300" type="percent"><!-- 30000% -->
</fmt:formatNumber>
<fmt:formatNumber var="i" value="300" type="percent"><!-- 30000% -->
</fmt:formatNumber>
${i}
<fmt:formatNumber value="10000" type="currency"><!-- ¥10000 默认是当前区域的货币符 -->
</fmt:formatNumber>
<fmt:formatNumber type="currency">
1000
</fmt:formatNumber>
<!-- pattern自定义模式 -->
<fmt:formatNumber value="10000"  pattern="¥"><!-- ¥10000 -->
</fmt:formatNumber>
<fmt:formatNumber value="10000"  pattern="$"><!-- $10000 -->
</fmt:formatNumber>
formatDate

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

<!--
	value 要显示的日期
	type date, time, 或 both date是年月日 time是时分秒 both两者都包含
	dateStyle full, long, medium, short, 或 default 可以设置date
	timeStyle full, long, medium, short, 或 default 可以设置time
	pattern 自定义格式模式
	timeZone 显示日期的时区
	var 存储格式化日期的变量名
	scope 存储格式化日志变量的范围
-->
<% request.setAttribute("time",new Date()); %><!-- 2019-9-11 -->
<fmt:formatDate value="${time}"/><br>
<fmt:formatDate value="${time}" var="t"/><br><!-- 2019-9-11 -->
<h1>${t}</h1>
<fmt:formatDate value="${time}" dateStyle="full"/><br><!-- 2019年9月11日 星期三 -->
<fmt:formatDate value="${time}" type="time" timeStyle="full"/><br>
<!-- 下午09时56分19秒 CST -->
<fmt:formatDate value="${time}" type="both" /><br><!-- 2019-9-11 21:56:19 -->
<fmt:formatDate value="${time}" type="both" timeStyle="full" dateStyle="full"/><br>
<!-- 2019年9月11日 星期三 下午09时56分19秒 CST -->
<fmt:formatDate value="${time}" pattern="yyyy/MM/dd hh:mm:ss"/><br>
<!-- 2019/09/11 09:56:19 -->
parseNumber

该标签可以将数字、货币或百分比的字符串表示法解析成指定语言环境的数字。 即解析一个代表着数字,货币或百分比的字符串。

<% 
	request.setAttribute("num", "$1,000.00"); 
	request.setAttribute("num1", "123,456.789"); 
%>
<!-- 无主体,值放在value属性中 pattern自定义解析模式 -->
<fmt:parseNumber value="Y2000" pattern="Y"></fmt:parseNumber><!-- 2000 -->
<!-- 有主体 -->
<fmt:parseNumber pattern="Y"><!-- 1000 -->
Y1000
</fmt:parseNumber>
<!-- 
	parseLocale指定解析数字时使用的区域,en_US指代美国 
	type可以为number、currency、percent
-->
<fmt:parseNumber value="${num}" type="currency" parseLocale="en_US"></fmt:parseNumber>
<fmt:parseNumber value="${num1}" type="number"></fmt:parseNumber>
parseDate

此标签为指定区域解析日期和时间的字符串表示法

<% request.setAttribute("time","14-11-18"); %>
<fmt:parseDate value="${time}" pattern="dd-MM-yy"><!-- Wed Nov 14 00:00:00 CST 2018  -->
</fmt:parseDate>