JSP Tag標籤
jsp tag標籤外表長得像html、xml等標記語言,但是內部其實就是封裝了的Java代碼。通過jsp標籤可以簡化一些需要在jsp上編寫的Java代碼,雖說是標籤,但是jsp只會在服務器上運行,不會跑到瀏覽器上運行,畢竟jsp歸根結底只是一個Servlet,以下介紹幾個常見的jsp標籤:
1.重定向標籤:
<jsp:forward page="index.jsp"></jsp:forward>
這個標籤與以下這段代碼等價,都是內部轉發:
<%
request.getRequestDispatcher("index.jsp").forward(request, response);
%>
index.jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<h1>Hello I'm index.jsp</h1>
</body>
</html>
使用Java代碼轉發示例:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
request.getRequestDispatcher("index.jsp").forward(request, response);
%>
</body>
</html>
訪問http://localhost:8080/jsp-tag_Test/test.jsp,運行結果:
Hello I'm index.jsp
使用jsp標籤轉發示例:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<jsp:forward page="index.jsp"></jsp:forward>
</body>
</html>
訪問http://localhost:8080/jsp-tag_Test/test.jsp,運行結果:
Hello I'm index.jsp
2.導入某頁面運行結果標籤:
<jsp:include page="head.jsp"></jsp:include>
這個標籤和jsp指令中的 <%@ include file="head.jsp" %> 類似,只不過指令是將head.jsp的頁面內容導入到當前頁面中,而jsp標籤則是僅導入head.jsp頁面的運行結果。它們兩者的區別在於這裏。使用示例:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<jsp:include page="index.jsp"></jsp:include>
</body>
</html>
訪問http://localhost:8080/jsp-tag_Test/test.jsp,運行結果:
Hello I'm index.jsp
3.配置參數標籤:
<jsp:param value="lisi" name="name"/>
這個標籤是用來配置參數的,比如轉發時帶上參數,或者導入某頁面結果時加上參數,不過這個標籤必須配合jsp:include、jsp:forward、jsp:plugin等標籤來進行使用,不然就會報以下錯誤:
嚴重: Servlet.service() for servlet [jsp] in context with path [/jsp-tag_Test] threw exception [/test.jsp (line: [9], column: [6]) The jsp:param action must not be used outside the jsp:include, jsp:forward, or jsp:params elements] with root cause
org.apache.jasper.JasperException: /test.jsp (line: [9], column: [6]) The jsp:param action must not be used outside the jsp:include, jsp:forward, or jsp:params elements
1.jsp:param與jsp:include配合使用:
test.jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<jsp:include page="index.jsp">
<jsp:param value="lisi" name="name" />
</jsp:include>
</body>
</html>
index.jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<h1><%=request.getParameter("name") %></h1>
</body>
</html>
訪問http://localhost:8080/jsp-tag_Test/test.jsp,運行結果:
lisi
2.jsp:param與jsp:forward配合使用:
test.jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<jsp:forward page="index.jsp">
<jsp:param value="lisi" name="name" />
</jsp:forward>
</body>
</html>
index.jsp代碼與之前一致。
訪問http://localhost:8080/jsp-tag_Test/test.jsp,運行結果:
lisi
以上三個標籤是比較常用的。
4.此標籤用來在jsp頁面中創建一個Bean實例:
<jsp:useBean id=""></jsp:useBean>
創建後的Bean示例可以存儲在request、session 、application(servletcontext)、page 等jsp內置對象中。
Java Bean簡介:
Java語言欠缺屬性、事件、多重繼承功能。所以,如果要在Java程序中實現一些面向對象編程的常見需求,只能手寫大量膠水代碼。Java Bean正是編寫這套膠水代碼的慣用模式或約定。這些約定包括getXxx、setXxx、isXxx、addXxxListener、XxxEvent等。遵守上述約定的類可以用於若干工具或庫。
使用jsp:useBean創建Bean實例對象,示例:
1.我有一個Student類,代碼如下:
public class Student {
private String sname;
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String email;
private int age;
}
2.test.jsp代碼如下:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<!-- id是這個對象的唯一標識,class裏的值是該類的全名,scope是指定該實例存儲在哪個內置對象中 -->
<jsp:useBean id="stu" class="org.zero01.test.Student" scope="request">這裏的文字會在對象創建的時候打印出來</jsp:useBean>
</body>
</html>
訪問http://localhost:8080/jsp-tag_Test/test.jsp,運行結果:
這裏的文字會在對象創建的時候打印出來
5.此標籤用於設置Bean對象的屬性值:
property的值爲對象的屬性名稱,name的值爲jsp:useBean中定義的id值,param的值爲html表單中的name屬性的值
<jsp:setProperty property="sname" name="stu" param="sname" />
6.此標籤用於得到Bean對象的屬性值,默認會將值打印出來:
同樣的property的值爲對象的屬性名稱,name的值爲jsp:useBean中定義的id值
<jsp:getProperty property="sname" name="stu" />
示例:
index.jsp代碼如下:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<form action="test.jsp">
<input type="text" name="form_sname" placeholder="學生名字" /><br>
<input type="text" name="form_email" placeholder="郵箱地址" /><br>
<input type="text" name="form_age" placeholder="年齡" /><br>
<button type="submit">提交</button>
</form>
</body>
</html>
test.jsp代碼如下:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<jsp:useBean id="stu" class="org.zero01.test.Student" scope="request">
這裏的文字會在對象創建的時候打印出來
</jsp:useBean><br>
<jsp:setProperty property="sname" name="stu" param="form_sname"/>
<jsp:setProperty property="email" name="stu" param="form_email"/>
<jsp:setProperty property="age" name="stu" param="form_age"/>
<jsp:getProperty property="sname" name="stu"/><br>
<jsp:getProperty property="email" name="stu"/><br>
<jsp:getProperty property="age" name="stu"/>
</body>
</html>
訪問http://localhost:8080/jsp-tag_Test/index.jsp,輸入的表單內容:
跳轉到test.jsp後的打印結果:
這裏的文字會在對象創建的時候打印出來 br/>lisi
[email protected]
15
如果表單中的name屬性值與Bean對象的屬性名稱一致的話,可以使用以下方式,自動匹配相同的名稱:
index.jsp表單代碼如下:
<form action="test.jsp">
<input type="text" name="sname" placeholder="學生名字" /><br>
<input type="text" name="email" placeholder="郵箱地址" /><br>
<input type="text" name="age" placeholder="年齡" /><br>
<button type="submit">提交</button>
</form>
test.jsp代碼如下:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<jsp:useBean id="stu" class="org.zero01.test.Student" scope="request">
這裏的文字會在對象創建的時候打印出來
</jsp:useBean><br>
<!-- property的值爲*會自動匹配表單中相同的名稱 -->
<jsp:setProperty property="*" name="stu"/>
<jsp:getProperty property="sname" name="stu"/><br>
<jsp:getProperty property="email" name="stu"/><br>
<jsp:getProperty property="age" name="stu"/>
</body>
</html>
訪問http://localhost:8080/jsp-tag_Test/index.jsp,輸入的表單內容:
跳轉到test.jsp後的打印結果:
這裏的文字會在對象創建的時候打印出來 br/>zero
[email protected]
16
關於Bean實例存儲在session對象中的那拿值過程:
<jsp:useBean id="stu" class="org.zero01.test.Student" scope="session">
1.先在session中查找有沒有stu
2.有的話就直接拿出來,不會創建對象
3.沒有的話,就創建對象,存到session中之後再拿出來
EL表達式
EL(Expression Language) 是爲了使JSP寫起來更加簡單。表達式語言的靈感來自於 ECMAScript 和 XPath 表達式語言,它提供了在 JSP 中簡化表達式的方法,讓Jsp的代碼更加簡化。EL表達式和jsp標籤一樣,內部實際就是java代碼,以下是生成的源碼:
使用EL表達式後生成的源碼:
out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${param.sname}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
使用jsp標籤後生成的源碼:
out.write("<br>\r\n");
out.write("\t\r\n");
out.write("\t<!-- property的值爲*會自動匹配表單中相同的名稱 -->\r\n");
out.write("\t");
org.apache.jasper.runtime.JspRuntimeLibrary.introspect(_jspx_page_context.findAttribute("stu"), request);
out.write("\r\n");
out.write("\t\r\n");
out.write("\t");
out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((org.zero01.test.Student)_jspx_page_context.findAttribute("stu")).getSname())));
out.write("<br>\r\n");
out.write("\t");
out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((org.zero01.test.Student)_jspx_page_context.findAttribute("stu")).getEmail())));
out.write("<br>\r\n");
out.write("\t");
out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((org.zero01.test.Student)_jspx_page_context.findAttribute("stu")).getAge())));
out.write("\r\n");
EL表達式的語法結構:
${expression}
基本語法示例:
${name}
以上這個表達式會拿到一個值,這個表達式的拿值過程:
1.先在當前頁面中的pageContext裏找有沒有這個名爲name的值
2.沒有的話就會去request對象裏找
3.request也沒有的話就去session裏找
4.session都沒有的話就去application(servletContext)裏找
5.如果在這些對象中都找不到的話也不會報錯,也不會打印null,而是什麼都不顯示。
示例:
test.jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<p>${name};</p>
</body>
</html>
訪問http://localhost:8080/EL-Test/test.jsp,顯示空白,因爲這個以上代碼並沒有表達式中所需要的值。
如果我在pageContext對象裏設置一個name屬性,看看是否能獲得到,代碼如下:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
pageContext.setAttribute("name", "lisi");
%>
<p>${name}</p>
</body>
</html>
訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
lisi
或者在request裏設置一個name屬性,代碼如下:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
request.setAttribute("name", "request");
%>
<p>${name}</p>
</body>
</html>
訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
request
以上實驗就可以知道,只要這些對象其中有一個name屬性值,就可以被這個表達式獲得到。以上也提到了這種表達式尋找值是先從pageContext對象中找的,所以來實驗一下是否是先從pageContext對象中找,代碼如下:
<%@page import="org.zero01.test.Student"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
request.setAttribute("name", "request");
session.setAttribute("name", "session");
pageContext.setAttribute("name", "pageContext");
application.setAttribute("name", "application");
%>
${name}
</body>
</html>
訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
pageContext
除了這種只寫屬性名稱讓它自動去匹配的方式之外,還可以指定在某個對象中拿值,如下:
${pageScope.name}
${requestScope.name}
${sessionScope.name}
${applicationScope.name}
還可以訪問某個對象的屬性,例如我在頁面上實例化了Student對象,設置了屬性值之後放進了request對象中,然後就可以通過el表達式去獲得這個Student對象的屬性值,示例:
<%@page import="org.zero01.test.Student"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
Student student = new Student();
student.setSname("lisi");
student.setAge(16);
student.setEmail("[email protected]");
request.setAttribute("student", student);
%>
${student.sname}<br>
${student.email}<br>
${student.age}<br>
</body>
</html>
訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
但是有一點要注意的就是,這個Student實例對象必須要有get方法才能獲得到相應的屬性值,否則是無法獲得的。
如果Student實例對象中有一個屬性存儲的是對象,那麼在el表達式中也可以拿到該對象的的屬性值:
<%@page import="org.zero01.test.Student"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%
Student stu = new Student();
stu.setSname("lisi");
stu.setAge(16);
stu.setEmail("[email protected]");
stu.setStudent(stu);
request.setAttribute("stu", stu);
%>
${requestScope.stu.student.sname}
<br>
${requestScope.stu.student.email}
<br>
${requestScope.stu.student.age}
<br>
</body>
</html>
訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
除了可以在以上對象中拿值外,還可在以下對象中拿值:
1.param: 表單參數對象
2.paramValues:重複的表單參數的對象
3.header: http請求頭參數對象
4.headerValues:重複的http請求頭參數的對象
5.cookie: cookie對象
6.initParam: 通過這個對象,可以拿到servletContxt對象初始化時配置的參數值
示例:
index.jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<form action="test.jsp">
<input type="text" name="sname" placeholder="學生名字" /><br>
<input type="text" name="sname" placeholder="學生名字" /><br>
<input type="text" name="sname" placeholder="學生名字" /><br>
<input type="text" name="email" placeholder="郵箱地址" /><br>
<input type="text" name="age" placeholder="年齡" /><br>
<button type="submit">提交</button>
</form>
</body>
</html>
test.jsp代碼:
<%@page import="org.zero01.test.Student"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
學生名字:${param.sname}<br>
郵箱地址:${param.email}<br>
年齡:${param.age}<br>
type:${paramValues.sname[2]}<br>
host:${header.host}<br>
Accept:${headerValues.Accept[0]}<br>
cookie:${cookie.JSESSIONID.value}<br>
</body>
</html>
訪問http://localhost:8080/EL-Test/index.jsp,輸入的表單內容如下:
跳轉到test.jsp後的打印結果:
學生名字:lisi1
郵箱地址:[email protected]
年齡:16
type:lisi3
host:localhost:8080
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
cookie:E936637B285D60CA96B7CC3D258EBD50
initParam 示例:
web.xml內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>name</param-name>
<param-value>一拳超人</param-value>
</context-param>
</web-app>
test.jsp代碼如下:
<%@page import="org.zero01.test.Student"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
${initParam.name}<br>
</body>
</html>
重啓Tomcat後,訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
一拳超人
el表達式除了可以從各種對象中獲得值之外還可以使用算術運算符、關係運算符、邏輯運算符等運算符,進行相關的運算,示例:
<%
request.setAttribute("num", "1000.5");
%>
${num / 100}<br>
${num * 100}<br>
${num + 100}<br>
${num - 100}<br>
${num % 100}<br>
${num == 1000.05}<br>
${num > 1000.05}<br>
${num < 1000.05}<br>
${num >= 1000.05}<br>
${num <= 1000.05}<br>
${num != 1000.05}<br>
${num == 1000.05 && true}<br>
${num == 1000.05 || false}<br>
${num != 1000.05 ? 8:9}<br>
訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
10.005
100050.0
1100.5
900.5
0.5
false
true
false
true
false
true
false
false
8
除了以上這種常見的運算符形式外,還可使用英文單詞縮寫的形式,(注意,加減乘,這三項不支持縮寫的形式)如下:
<%
request.setAttribute("num", 1000.5);
%>
${num div 100}<br>
${num * 100}<br>
${num + 100}<br>
${num - 100}<br>
${num mod 100}<br>
${num eq 1000.05}<br>
${num gt 1000.05}<br>
${num lt 1000.05}<br>
${num ge 1000.05}<br>
${num le 1000.05}<br>
${num ne 1000.05}<br>
${num eq 1000.05 and true}<br>
${num eq 1000.05 or false}<br>
${num ne 1000.05 ? 8:9}<br>
訪問http://localhost:8080/EL-Test/test.jsp,打印結果如下:
10.005
100050.0
1100.5
900.5
0.5
false
true
false
true
false
true
false
false
8
關於OGNL表達式:
OGNL是Object-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言,通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。它使用相同的表達式去存取對象的屬性。所以OGNL和EL表達式蠻像的,在一些需要動態變化字段的場景下,OGNL非常的有用,例如流程控制語句中的條件需要動態變化的情況下,就需要使用OGNL。
下面簡單演示一下OGNL,maven工程配置如下依賴:
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.0.4</version>
</dependency>
編寫代碼如下:
package org.zero01.test;
import java.util.Hashtable;
import ognl.Ognl;
import ognl.OgnlException;
public class TestOGUL{
public static void main(String[] args) throws OgnlException {
Student stu=new Student();
//使用hashtable作爲表達式的root,也就是根元素
Hashtable<String, Object> hashtable=new Hashtable<String, Object>();
hashtable.put("stu", stu);
//設置一個表達式
Ognl.setValue("stu.sname", hashtable, "李四");
//得到表達式的值
System.out.println(Ognl.getValue("stu.sname", hashtable));
//還可以進行運算
System.out.println(Ognl.getValue("100*(500+90)*(500+90)", hashtable));
}
}
運行結果:
李四
34810000
以上只是一個十分簡單的示例,目的是爲了稍作了解而已,知道除了EL表達式外還有這種表達式。