Java_JSP入门
JSP
简介
JSP对比html 而言,html 只能为用户提供静态数据,而 Jsp 技术允许在页面中嵌套 java 代码,为用户提供动态数据。
相比 servlet 而言,servlet 很难对数据进行排版,而 jsp 除了可以用 java 代码产生动态数据的同时,也很容易对数据进行排版。
不管是 JSP 还是 Servlet,虽然都可以用于开发动态 web 资源。但由于这 2 门技术各自的特点,在长期的软件实践中,人们逐渐把 servlet 作为 web 应用中的控制器组件来使用, 而把 JSP 技术作为数据显示模板来使用。
其实 Jsp 就是一个 Servlet,当我们第一次访问 Jsp 的时候,Jsp 引擎都会将这个 Jsp 翻译 成一个 Servlet,这个文件存放在tomcat(源码目录) 中的 work 目录中。
-C:\Users\alion\.IntelliJIdea2019.2\system\tomcat\Tomcat_9_0_30_WebPro1\work\Catalina\localhost\alion01\org\apache\jsp
注释
JSP 有3种注释的方式
-
html注释方式——<!—注释内容->
这种方式注释jsp代码。如果代码有问题。运行的时候还是会报错的。所以不靠谱 但是这种方式是显示注释,可以被浏览器解析。一般不用。
-
java方式注释——在<%%>中使用。
用来注释java代码。 是隐式注释。不会被浏览器读取
-
<%-- JSP 注释 --%>
jsp方式注释。在jsp页面中使用这种方式注释就好。
Scriptlet
在 JSP 中最重要的部分就是 Scriptlet(脚本小程序),所有嵌入在 HTML 代码中的 Java 程序。
在 JSP 中一共有三种 Scriptlet 代码:都必须使用 Scriptlet 标记出来
-
<% %> ——java脚本段,可以定义局部变量、编写语句
定义在这范围中的代码,会被tomcat解析到service方法中。并且是从上往下解析 因此不同的<%%>中的变量可以访问到。其实就和在service方法中写语句一样。没区别
<%
String name ="1234";
%>
<%
System.out.println(name);
%>
-
<%! %> ——用来声明 全局的变量、方法 、和类。
定义的方法会作为 编译后的Servlet类的 方法,而类会作为内部类存在。 声明的变量会被定义为全局变量
<%!
public void name(){
System.out.println("你好呀");
}
%>
<%!
class Person{
private String name;
}
%>
-
<%= %> ——定义表达式。存储一个变量或者具体的内容
在编译后的Servlet类中 以 out.print(name);方式输出。会在页面中显示该变量 所以可以用来做 显示一个具体内容或者变量。相当于在页面中写了out.print();
Include标签(指令标签)
使用包含操作,可以将一些重复的代码包含进来继续使用,从正常的页面组成来看,有时可能分为几个区域。而其中的一些区域可能是一直不需要改变的,改变的就其中的一个具体内容区域。
include 静态包含
<%@ include file=“要包含的文件路径” %> ——file中写相对路径
只能包含本地资源文件,可以是jsp文件,也可以是html页面
<%@include file="index.jsp"%>//index.jsp为同级页面。
静态包含就是将内容进行了直接的替换,就好比程序中定义的变量一样,是在 servlet 引擎转译时,就把此文件内容包含了进去(两个文件的源代码整合到一起, 全部放到_jspService 方法中),所以只生成了一个 servlet,所以两个页面不能有同名的变量。 运行效率高一点点。耦合性较高,不够灵活。
include 动态包含
动态包含在代码的编译阶段,包含和被包含部分是两个独立的部分,只有当运行时,才会动态包含进来,好比方法的调用。
-<jsp:include page="include.jsp"></jsp:include>
注意:动态包含,中间不要加任何内容,包括空格,除非确认要使用参数,否则报错!
<%
String a = "hello.jsp";
%>
<jsp:include page="<%=a %>"></jsp:include> //通过<%=%>来使用变量。
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, a , out, false);
a变量通过参数的形式传入。如果直接写地址,则a变量处为对应字符串。
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, “index.jsp”, out, false);
传参
使用动态包含还可以通过在页面之间传参。
传参时候,name是参数名,value是值。 value支持表达式。
接收参数通过 request.getParameter(name);
<jsp:include page="hello.jsp" flush="true">
<jsp:param name="uname" value="zhangsan"/> //请求参数。
</jsp:include>
<!-- 接收参数 -->
<%=request.getParameter("uname")%>
会生成多个class文件。并且是方法的调用方式。
-index.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("uname", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("zhangsan", request.getCharacterEncoding())
接受参数通过拼接字符串的形式。 写在请求中。相当于参数是请求中转过去的。
JSP的四大域对象
四种属性范围
在JSP中提供了四种属性的保存范围,所谓的属性保存范围,指的就是一个设置的对象,可以再多少个页面中保存并可以继续使用
-
page范围
是内置对象。可以通过 pageContext : 只在一个页面中保存属性,跳转之后无效 本页面取得,服务器端跳转(<jsp :forward>)后无效
-
request范围
equest : 只在一次请求中保存,服务器跳转后依然有效(请求跳转) 如果是客户端跳转,则相当于发出了两次请求,那么第一次的请求将不存在了;
-
session范围
session : 在一次会话范围中,无论何种跳转都可以使用 无论客户端还是服务器端都可以取得,但是现在重新开启一个新的浏览器,则无法取得之前 设置的session了,因为每一个session只保存在当前的浏览器当中,并在相关的页面取得
-
application范围
application : 在整个服务器上保存,不管哪个用户 都可以访问。 只要是通过application设置的属性,则所有的session都可以取得,表示公共的内容
使用方法
- public void setAttribute(String name, Object o)——设置域对象属性。
- public Object getAttribute(String name)——根据属性名称取属性
- public void removeAttribute(String name)——删除指定的属性。
EL表达式的使用
EL表达式的语法
EL(Expression Language) 是为了使 JSP 写起来更加简单。它简化了表达式的写法。使得代码更加简便,不用像之前使用<%=%>来使用。
语法
-${expression}
EL操作的是域对象中的数据,不能操作变量,因为EL表达式是去域对象中查找数据的。。变量还是需要用<%=%>
域对象的概念在 JSP 中一共有四个:pageContext, request, session, application;范围依次是,本页面,一次请求, 一次会话,整个应用程序。
EL表达式寻找数据时候也是从小到大的顺序开始找
从page开始找——>request ——> session——>application 都没找到则返回空串(默认值)。
如果需要查找指定单位的域对象的值。那么可以使用pageScope, requestScope, sessionScope, applicationScope来指定查找哪个域对象
- 获取指定域对象值
-${pageScope.uname}
——查找page中的域对象值,没有则返回空串
-
获取List
-${list[下标]}
——获取集合指定下标的值
-${list.size()}
——获取集合长度list代表的是存在域对象中的变量名(限域变量名)
-
获取Map
-${map["key"] } 或 ${map.key }
——根据key值获取value。map代表的是存在域对象中的变量名(限域变量名)
-
获取JavaBean对象
-${user}
——获取对象
-user.uname
——获取对象中的属性
-user.getUname()
——获取对象中的属性方式2,直接调用get方法。
(javabean对象必须提供get方法。实际上是调用get方法)
empty判断
判断域对象是否为空。为空,返回true;不为空返回false;
-${empty 限域变量名 }
判断对象是否不为空。
-${!empty 限域变量名 }
-
不存在的域对象(null)
返回ture
-
String 情况
空字符串 返回true 只有在有值,且不为空字符串 返回false
-
list 情况
没有长度 返回true 只有有值才返回false
-
map 情况
和list相同
-
javabean 情况
只要对象存在,不管有没有值都返回false。 new了对象就算不为空
EL运算、判断、比较
比较
-== 或 eq
——比较两个值是否相等
${a == b } || ${a == 5 } || ${c eq 'aa' }
算术运算
-+,-,*,/
——除法可以用div代替。
${a + b } ||${a / b } || ${a div b }
大小比较
->,<,<=,>=
——比较大小
${a > b && b > 5 }||${a + b > 10 || a - b > 5 } 逻辑运算符和java中一致。
JSTL技术
标签的使用
ava Server Pages Standard Tag Libray(JSTL):JSP 标准标签库,是一个定制标签类库的集合,用于解决一些常见的问题,例如迭代一个映射或者集合、条件测试、XML 处理,甚至数据库和访问数据库操作等。
核心标签库:http://java.sun.com/jsp/jstl/core
包含 Web 应用的常见工作,比如:循环、表达式赋值、基本输入输出等。
格式化标签库:http://java.sun.com/jsp/jstl/fmt
用来格式化显示数据的工作,比如:对不同区域的日期格式化等。
为了在 JSP 页面使用 JSTL 类库,必须以下列格式使用 taglib 指令:
-<%@taglib uri="" prefix="" %>
uri中填标签库地址,prefix(前缀)相当于该标签库的别名。
使用前需要导入
下载地址:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/
下载 jakarta-taglibs-standard-1.1.2.zip 包并解压,将 jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar 文件:standard.jar 和 jstl.jar 文件拷贝到项目的指定目录下。
条件动作标签
if标签
if 标签先对某个条件进行测试,如果该条件运算结果为 true, 则处理它的主体内容,测试结果保存在一个 Boolean 对象中,并创建一个限域变量来引用 Boolean 对象。可以利用 var 属性设置限域变量名,利用 scope 属性来指定其作用范围。
test中表示进行的Boolean判断,var中存储test返回的结果,scope可以指定限于变量名范围
<c:if test="<boolean>" var="<string>" scope="<string>">
...
</c:if>
JSTL中没有else标签
<c:if test="${flag}">
<p>结果为true<p>
</c:if>
choose、when 和 otherwise 标签
choose 和 when 标签的作用与 Java 中的 switch 和 case 关键字相似,用于在众多选项中做出选择。也就是说:他们为相互排斥的条件式执行提供相关内容。
<c:choose>
<c:when test="<boolean>">
...
</c:when>
<c:when test="<boolean>">
...
</c:when>
...
...
<c:otherwise>
...
</c:otherwise>
</c:choose>
choose标签没有属性。
when标签只有一个test属性。
otherwise标签没有属性。
注意
1、choose标签和otherwise标签没有属性,而when标签必须设置test属性
2、hoose标签中必须有至少一个when标签,可以没有otherwise标签
3、otherwise标签必须放在最后一个when标签之后
4、choose标签中只能有when标签和otherwise标签,when标签和otherwise标签可以嵌套其他
5、otherwise标签在所有的when标签不执行的情况下才会执行
迭代标签
forEach 是将一个主体内容迭代多次,或者迭代一个对象集合。可以迭代的对象包括所有的 java.util.Collection 和 java.util.Map 接口的实现,以及对象或者基本类型的数组。他还可 以迭代 java.util.Iterator 和 java.util.Enumeration,但不能在多个动作指令中使用 Iterator 或者 Enumeration,因为 Iterator 或者 Enumeration 都不能重置(reset)
<c:forEach
items="<object>" 表示迭代的对象
begin="<int>" 起始数值。相当于for循环中定义的int i=0;
end="<int>" 末尾位置。相当于for循环定义的i<10;这个10;
step="<int>" 步长。相当于for循环中定义的i++ ;
var="<string>" 限域变量名称。
varStatus="<string>">循环的状态。
</c:forEach>
forEach varStatus 属性
index: 当前这次迭代从 0 开始的迭代索引
count: 当前这次迭代从 1 开始的迭代计数
first: 用来表明当前这轮迭代是否为第一次迭代的标志
last: 用来表明当前这轮迭代是否为最后一次迭代的标志
- 普通for循环方式
<c:forEach begin="开始数" end="结束数" step="迭代数" var="限域变量名">
</c:forEach>
- 增强for循环方式
<c:forEach items="被循环的集合" var="限域变量名" varStatus="当前成员对象的相关信息">
</c:forEach>
遍历map
<c:forEach items="${map}" var="mymap">
键:${mymap.key }-值:${mymap.value } <br>
</c:forEach>
格式化动作标签
JSTL 提供了格式化和解析数字和日期的标签,我们讨论里面有:formatNumber、formatDate、parseNumber及parseDate。
formatNumber标签
formatNumber标签用于格式化数字,百分比,货币。该标签用指定的格式或精度来格式化数字。(将数值型数据转换成指定格式的字符串类型。)
<fmt:formatNumber
value="<string>" 要格式化的值
type="<string>" NUMBER,CURRENCY,或 PERCENT类型 格式化的类型
var="<string>" 存储格式化数字的变量 限域变量名
scope="<string>"/> 作用域
<fmt:formatNumber value="10" type="number" var="num" /> ${num } <br>
<fmt:formatNumber value="10" type="percent" /> <br>
<fmt:formatNumber value="10" type="currency" /> <br>
<!-- 设置时区 -->
<fmt:setLocale value="en_US"/>
<fmt:formatNumber value="10" type="currency" /> <br>
formatDate标签 (最为重要)
formatDate标签用于使用不同的方式格式化日期。(将Date型数据转换成指定格式的字符串类型。)
<fmt:formatDate
value="<string>" 要格式化的值
type="<string>" 格式化的类型
dateStyle="<string>" 日期格式化的样式
timeStyle="<string>" 时间格式化的样式
pattern="<string>" 自定义样式
timeZone="<string>" 显示时区
var="<string>" 限域变量名
scope="<string>"/> 变量范围
-<fmt:formatDate value="${myDate }" pattern="HH:mm yyyy/MM/dd"/><br/>
自定义格式化
-<fmt:formatDate value="${myDate }" type="both"/><br/>
两种格式都包含
-<fmt:formatDate value="${myDate }" type="date"/><br/>
日期格式
用setLocale来设置时区
parseNumber标签
parseNumber标签用来解析数字,百分数,货币。(parseNumber 标签可以将数字、货币或百分比类型的字符串转换成数值型) 就是反转。
<fmt:parseNumber
value="<string>"
type="<string>"
var="<string>"
scope="<string>"/>
parseDate标签
parseDate标签用于解析日期。(将指定格式的字符串转换成Date类型)
<fmt:parseDate
value="<string>"
type="<string>"
dateStyle="<string>"
timeStyle="<string>"
pattern="<string>"
var="<string>"
scope="<string>"/>
实例
<fmt:parseDate value="2020-01-06" type="date" /> <br> 默认格式
<fmt:parseDate value="2020/01/06" pattern="yyyy/MM/dd" /> <br>`