Javaweb之jsp详解
1. JSP指令元素
1.1. page指令
page指令是JSP页面中最常用的指令,用来声明JSP页面的属性等信息。一个page指令允许定义多个属性;也可以一个page指令定义一个属性,定义多个page指令。
<!-- 一个page指令,设置多个属性 -->
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 一个page指令,设置一个属性.配置多个page指令 -->
<%@ page import="java.util.*"%>
<%@ page pageEncoding="UTF-8"%>
但是需要注意的是:
- page指令设置的属性只能出现一次,除import属性以外。
- 属性名称区分大小写。
page指令允许的属性如下:
属性名称 | 取值范围 | 描述 |
---|---|---|
language | java | 指明该JSP文件采用的语言。 |
extends | 任何类的全名 | 指明该JSP文件继承于哪个类。JSP为Servlet,因此当指明继承普通类时需要实现Servlet的init()、destroy()等方法。 |
import | 任何包名、类名 | 引入该JSP中用到的类、包等。import是唯一可以声明多次的page指令属性。一个import属性可以引用多个类,中间用英文逗号隔开。JSP中下面四个包里的类可以直接使用:java.lang.,javax.servlet.,javax.servlet.jsp.,javax.servlet.http.。 |
session | true,false | 指明该JSP内是否内置Session对象。如果为true,则内置Session对象,可直接使用。否则不内置Session对象。默认为true |
autoFlush | true,false | 是否运行缓存。如果为true,则使用out.println()等方法输出的字符串并不是立刻到达服务器端的,而是暂时存在缓存里,缓存满或者程序执行完毕或者执行out.flush()操作时才到客户端。默认为true |
buffer | none、数字+KB | 指定缓存大小,当autoFlush设为true时有效,默认值为8KB。 |
isThreadSafe | true,false | 指定是否线程安全。如果为true,则运行多个线程同时运行该JSP程序,否则只运行一个线程运行,其余线程等待。默认为false |
isErrorPage | true,false | 指定该页面是否为错误处理页面。如果为true,则该JSP内置Exception对象,可直接使用,否则没有。默认为false |
errorPage | 某个JSP页面的相对路径 | 指明一个错误显示页面,如果该JSP程序抛出一个未捕捉的异常,则转到errorPage指定的页面。errorPage指定的页面通常isErrorPage属性为true,且内置Exception对象为未捕捉的异常。 |
contentType | 有效的文档类型 | 客户端浏览器根据该属性判断文档类型。 |
info | 任意字符串 | 指明该JSP的信息,该信息可以通过Servlet.getServletInfo()方法获取。 |
trimDirective Whitespaces | true,false | 是否去掉指令前后的空白字符。默认为false |
isELIgnored | true,false | 指明当前页面是否忽略EL表达式。默认为false,表示不忽略。 |
-
pageEncoding
和
contentType
属性
- pageEncoding属性:指明当前JSP页面使用的编码格式。pageEncoding属性的值要与JSP页面的真实编码保持一致,否则会出现乱码。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
-
- contentType属性:在JSP页面编译成Servlet文件时,对应response.setContentType()方法。
pageEncoding属性与contentType属性只设置其中一个属性时,另一个属性的默认与设置的相同。如果两个属性都不设置的话,两个属性的默认值都为“ISO-8859-1”。一般情况下,至少设置其中一个。
-
errorPage
和
isErrorPage
属性
- 创建一个JSP页面,编写代码如下:
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'page.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
This is my JSP page. <br>
<%
if(true){
throw new RuntimeException();
}
%>
</body>
</html>
[](javascript:void(0)😉
-
- 发布Web工程,并访问http://localhost:8080/jsp/01_directive/page.jsp。
页面访问报错,提示JSP页面的throw new RuntimeException();这句报错。当页面报错时,是不希望用户看到这样的错误页面,而是友好的错误信息。
-
- 创建一个JSP页面,用于页面报错的友好提示信息。
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'error.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
this is error page.<br>
</body>
</html>
[](javascript:void(0)😉
-
- 在第一个JSP页面中增加如下代码,设置如果当前页面出现错误,利用error.jsp页面进行错误信息的提示。
<%@ page language="java" pageEncoding="UTF-8" errorPage="error.jsp"%>
-
- 重新发布Web工程,并访问http://localhost:8080/jsp/01_directive/page.jsp。
这时再次访问当前的JSP页面,会发现显示的是error.jsp页面的内容。这样的处理使得报错更好友,但是还存在一个问题,就是通过HttpWatch工具抓取会发现响应状态码为200,并不是错误的状态码。这就说明了虽然页面报错并进行了相关提示,但实际上JSP页面将错误隐藏起来,这样不利于之后的处理。
-
- 在error.jsp页面中增加如下代码,设置如果当前JSP页面错误,响应对应的状态码,以便之后处理。
<%@ page language="java" pageEncoding="UTF-8" isErrorPage="true"%>
-
- 重新发布Web工程,并访问http://localhost:8080/jsp/01_directive/page.jsp。
-
- 在error.jsp页面中,可以使用JSP内置对象exception获取异常信息等功能,该对象只能在错误页面中。
[](javascript:void(0)😉
<%@ page language="java" pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'error.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
this is error page.<br>
<%=exception.getMessage() %>
</body>
</html>
[](javascript:void(0)😉
-
- 在JSP页面中指定错误页面虽然可以,但是操作繁琐(实际开发要为每一个JSP页面指定)。还可以使用web.xml文件配置错误页面信息。
[](javascript:void(0)😉
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd">
<!-- 配置对应状态码为404的错误页面 -->
<error-page>
<!-- 设置对应的状态码 -->
<error-code>404</error-code>
<!-- 配置错误页面路径 -->
<location>/directive/error.jsp</location>
</error-page>
<!-- 配置对应异常的错误页面 -->
<error-page>
<!-- 设置对应的异常 -->
<exception-type>java.lang.RuntimeException</exception-type>
<!-- 配置错误页面路径 -->
<location>/directive/error.jsp</location>
</error-page>
</web-app>
[](javascript:void(0)😉
1.2. include指令
include指令用于在JSP页面中静态包含另一个文件,该文件可以是JSP页面、HTML页面、文本文件或一段Java代码。include语法格式如下:
<%@ include file="包含文件的路径" %>
设置包含文件的路径只能是常量,不能是变量。
include.jsp页面:
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'include.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
欢迎你,现在的时间是:
<%@ include file="date.jsp" %>
</body>
</html>
[](javascript:void(0)😉
date.jsp页面
<%
out.println(new java.util.Date().toString());
%>
1.3. taglib指令
JSP页面支持标签,使用标签功能可以实现视图代码重用,很少量的代码可以实现很复杂的显示效果。要使用标签功能必须先声明标签库以及标签前缀。taglib指令用于指明JSP页面使用的JSP标签库。taglib指令的语法格式如下:
<%@ taglib prefix="标签前缀" uri="标签库的完整路径" %>
目前使用最多的是如下标签库:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2. JSP动作标签
2.1. jsp:include标签
这个动作标签用于在当前页面中包含静态和动态的资源,一旦被包含的页面执行完毕,请求处理将在调用页面中继续进行。这个动作标签与javax.servlet.RequestDispatcher类的include方法一致。
<jsp:include flush="boolean值" page="被包含页面的路径"></jsp:include>
- flush属性:该属性是可选的。默认值为false,表示当前页面输出使用了缓冲区,在包含之前不刷新缓冲区。true表示刷新缓冲区。
- page属性:指定被包含资源的相对路径,该路径是相对于当前JSP页面的URL。
include标签与include指令的区别:
语法 | 相对路径 | 发生时间 | 包含的对象 | 描述 |
---|---|---|---|---|
<%@ include file=”url”%> | 相对于当前文件 | 转换期间 | 静态 | 包含的内容被JSP容器分析 |
<jsp:include page=”url”> | 相对于当前页面 | 请求处理期间 | 静态和动态 | 包含的内容不进行分析 |
2.2. jsp:forward标签
这个动作标签运行在运行时将当前的请求转发给一个静态的资源、JSP页面或者Servlet,请求被转向到的资源必须位于同JSP发送请求相同的上下文环境中。这个动作标签与javax.servlet.RequestDispatcher类的forward()方法的作用相同。
这个动作标签的语法格式如下:
<jsp:forward page="请求转发到页面的路径"></jsp:forward>
具体用法如下:
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'forward.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<h1>forward.jsp</h1>
<% System.out.println("forward jsp start..."); %>
<jsp:forward page="include.jsp?flag=true"></jsp:forward>
<% System.out.println("forward jsp end..."); %>
</body>
</html>
[](javascript:void(0)😉
转换成Servlet后的代码
[](javascript:void(0)😉
out.write(" \t<h1>forward.jsp</h1>\r\n");
out.write(" \t");
System.out.println("forward jsp start...");
out.write("\r\n");
out.write(" ");
if (true) {
_jspx_page_context.forward("include.jsp?flag=true");
return;
}
out.write("\r\n");
out.write(" ");
System.out.println("forward jsp end...");
[](javascript:void(0)😉
2.3. jsp:param标签
这个动作标签与jsp:include标签、jsp:forward标签配合使用,以键值对形式为其他标签提供参数内容。这个动作标签的语法格式如下:
<jsp:param value="参数值" name="参数名称"/>
具体用法参考如下代码:
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'forward.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<jsp:forward page="include.jsp">
<jsp:param value="true" name="flag"/>
</jsp:forward>
</body>
</html>
[](javascript:void(0)😉
3. JSP内置对象
3.1. out输出流对象
内置对象out是javax.servlet.jsp.JspWriter类的实例,与response.getWriter()方法的作用相同,都是服务器端向客户端输出的字符串内容。该对象的常用方法如下:
Method Summary | |
---|---|
abstract void | clear() Clear the contents of the buffer. |
abstract void | flush() Flush the stream. |
int | getBufferSize() This method returns the size of the buffer used by the JspWriter. |
abstract int | getRemaining() This method returns the number of unused bytes in the buffer. |
boolean | isAutoFlush() This method indicates whether the JspWriter is autoFlushing. |
abstract void | print(String s) Print a string. |
abstract void | println(String x) Print a String and then terminate the line. |
3.2. pageContext上下文对象
内置对象pageContext是javax.servlet.jsp.PageContext类的实例,该对象是JSP的四大作用域对象之一,pageContext对象代表当前JSP页面编译后的内容,多用于JSP页面之间共享数据内容。
- pageContext对象的常用方法
Method Summary | |
---|---|
abstract Object | getAttribute(String name) Returns the object associated with the name in the page scope or null if not found. |
abstract void | removeAttribute(String name) Remove the object reference associated with the given name from all scopes. |
abstract void | [setAttribute](https://www.cnblogs.com/aaron911/p/7799265.html#setAttribute(java.lang.String, java.lang.Object))(String name, Object value) Register the name and value specified with page scope semantics. |
- pageContext对象获取其他八个内置对象
Method Summary | |
---|---|
abstract JspWriter | getOut() The current value of the out object (a JspWriter). |
abstract Exception | getException() The current value of the exception object (an Exception). |
abstract Object | getPage() The current value of the page object (In a Servlet environment, this is an instance of javax.servlet.Servlet). |
abstract ServletRequest | getRequest() The current value of the request object (a ServletRequest). |
abstract ServletResponse | getResponse() The current value of the response object (a ServletResponse). |
abstract ServletConfig | getServletConfig() The ServletConfig instance. |
abstract ServletContext | getServletContext() The ServletContext instance. |
abstract HttpSession | getSession() The current value of the session object (an HttpSession). |
- pageContext对象操作其他三个域
Method Summary | |
---|---|
abstract Object | findAttribute(String name) Searches for the named attribute in page, request, session (if valid), and application scope(s) in order and returns the value associated or null. |
abstract Object | [getAttribute](https://www.cnblogs.com/aaron911/p/7799265.html#getAttribute(java.lang.String, int))(String name, int scope) Return the object associated with the name in the specified scope or null if not found. |
abstract void | [removeAttribute](https://www.cnblogs.com/aaron911/p/7799265.html#removeAttribute(java.lang.String, int))(String name, int scope) Remove the object reference associated with the specified name in the given scope. |
abstract void | [setAttribute](https://www.cnblogs.com/aaron911/p/7799265.html#setAttribute(java.lang.String, java.lang.Object, int))(String name, Object value, int scope) Register the name and value specified with appropriate scope semantics. |
上述方法中的scope参数表示其他三个域常量:
Field Summary | |
---|---|
static int | APPLICATION_SCOPE Application scope: named reference remains available in the ServletContext until it is reclaimed. |
static int | REQUEST_SCOPE Request scope: the named reference remains available from the ServletRequest associated with the Servlet until the current request is completed. |
static int | SESSION_SCOPE Session scope (only valid if this page participates in a session): the named reference remains available from the HttpSession (if any) associated with the Servlet until the HttpSession is invalidated. |
3.3. request请求对象
内置对象request是javax.servlet.ServletRequest类的实例,代表着客户端的请求。具体用法请参考Request对象内容。
3.4. response响应对象
内置对象response是javax.servlet.ServletResponse类的实例,代表着服务器端的响应。具体用法请参考Response对象内容。
3.5. config配置对象
内置对象config是javax.servlet.ServletConfig类的实例,ServletConfig对象封装了配置在web.xml文件中初始化JSP的参数,JSP通过config对象获取这些参数值。具体用法请参考ServletConfig对象内容。
3.6. session会话对象
内置对象session是javax.servlet.http.HttpSession类的实例,session与cookie是解决Http协议的无状态问题的两种解决方案。如果在JSP页面中使用<%@ page session=”false”%>指令的话,则在当前JSP页面中不能使用session内置对象。但一般情况下,不会禁止使用session对象,具体用法请参考HttpSession对象内容。
3.7. application应用对象
内置对象application是javax.servlet.ServletContext类的实例,ServletContext封装了JSP所在的Web应用程序的信息,整个Web应用程序对应一个ServletContext对象。具体用法请参考ServletContext对象内容。
3.8. page页面对象
内置对象page是javax.servlet.jsp.HttpJspPage类的实例,page对象代表当前JSP页面,是当前JSP编译后的Servlet类的对象。page相当于普通Java类中的关键字this。
3.9. exception异常对象
内置对象exception是java.lang.Exception类的实例,该对象封装了JSP中抛出的异常信息。exception对象只能在使用<%@ page isErrorPage=”true”%>指令的JSP页面中。
4. JSP与JavaBean
4.1. JavaBean概述
JavaBean本质上就是一个Java类,只不过这个类需要遵循一些编码的规范。在JSP页面中,既可以使用普通类一样实例化JavaBean类的对象,调用方法,也可以利用JSP提供的动作标签访问JavaBean。
一个标准的JavaBean具有以下几个特性:
- 是一个公开(public)的类。
- 有一个默认的无参构造方法。
- 提供Setter和Getter方法用于设置和获取JavaBean的属性。
换句话讲,只要是符合上述条件的类,都可以看作是JavaBean。下面就是一个JavaBean实例:
[](javascript:void(0)😉
public class User {
public String name;
public Boolean married;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean isMarried() {
return married;
}
public void setMarried(Boolean married) {
this.married = married;
}
}
[](javascript:void(0)😉
4.2. 内省
SUN公司开发了一套API,方便更好地操作JavaBean的属性,这套API被称之为内省(Introspector)。内省的出现有利于对JavaBean的属性操作,减少了代码量,内省依赖于Java的反射。
通过内省来操作JavaBean的属性,具体步骤如下:
- 通过Class类对象获取BeanInfo实例。
- 通过BeanInfo实例获取所有属性描述符对象。
- 通过属性描述符对象操作对应JavaBean的属性。
[](javascript:void(0)😉
public class Demo {
@Test
public void Demo() throws Exception{
Class c = User.class;
Object obj = c.newInstance();
//1 通过Class类对象获取BeanInfo实例
BeanInfo info = Introspector.getBeanInfo(User.class);
//2 通过BeanInfo实例获取所有属性描述符对象
PropertyDescriptor[] pds = info.getPropertyDescriptors();
/*
* 3 通过属性描述符对象操作对应JavaBean的属性
* * 获取属性名称
* * 获取读方法
* * 获取写方法
*/
for (PropertyDescriptor pd : pds) {
// 获取并输出JavaBean的属性名称
System.out.println(pd.getName());
// 获取并输出JavaBean的属性类型
System.out.println(pd.getPropertyType());
// 判断当前获取的JavaBean的属性名称是否为"name"
if (pd.getName().equals("name")) {
// 获取JavaBean的name属性的写方法
Method wmd = pd.getWriteMethod();
wmd.invoke(obj, "longestory");
// 获取JavaBean的name属性的读方法
Method rmd = pd.getReadMethod();
System.out.println(rmd.invoke(obj));
}
}
}
}
[](javascript:void(0)😉
4.3. BeanUtils工具
虽然Java提供了反射和内省相关的API,用于操作JavaBean组件的属性。但这些API方法使用起来很复杂,BeanUtils工具是Apache基于Java的内省封装的一个工具包。
BeanUtils工具包使用时,需要依赖logging日志包。
- 通过BeanUtils工具操作JavaBean的属性相关简单了不少。
[](javascript:void(0)😉
public class Demo {
@Test
public void Demo() throws Exception{
Class c = User.class;
Object obj = c.newInstance();
BeanUtils.setProperty(obj, "name", "longestory");
BeanUtils.setProperty(obj, "age", "14");
BeanUtils.setProperty(obj, "married", true);
String name = BeanUtils.getProperty(obj, "name");
System.out.println(name);
}
}
[](javascript:void(0)😉
- 通过BeanUtils工具的populate()方法来操作JavaBean。
[](javascript:void(0)😉
public class Demo {
@Test
public void Demo() throws Exception{
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "longestory");
map.put("age", "18");
map.put("married", true);
Class c = User.class;
Object obj = c.newInstance();
BeanUtils.populate(obj, map);
System.out.println(obj);
}
}
[](javascript:void(0)😉
- 通过populate()方法将一个Map集合内容设置到对应的JavaBean中,自定义一个工具类来完成复用。
[](javascript:void(0)😉
public class CommonUtils {
public static <T> T toBean(Map map, Class<T> clazz) {
try {
T bean = clazz.newInstance();
BeanUtils.populate(bean, map);
return bean;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
[](javascript:void(0)😉
下面通过一个案例来掌握BeanUtils封装内省的内容。
- 创建一个JSP页面用于显示用户注册信息。
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>用户注册页面</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<form action="/12_jsp/regist" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
确认密码:<input type="password" name="repassword"/><br/>
邮箱:<input type="text" name="email"/><br/>
<input type="submit" value="注册"/>
</form>
</body>
</html>
[](javascript:void(0)😉
- 创建一个JavaBean用于封装用户注册信息。
[](javascript:void(0)😉
public class Person {
private String username;
private String password;
private String email;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Person [username=" + username + ", password=" + password + ", email=" + email + "]";
}
}
[](javascript:void(0)😉
- 创建一个Servlet用于接收用户注册信息。
[](javascript:void(0)😉
public class PersonServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Person person = CommonUtils.toBean(request.getParameterMap(), Person.class);
System.out.println(person);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
[](javascript:void(0)😉
- 配置Web工程的web.xml文件。
[](javascript:void(0)😉
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd">
<display-name></display-name>
<servlet>
<servlet-name>PersonServlet</servlet-name>
<servlet-class>app.java.exam.PersonServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PersonServlet</servlet-name>
<url-pattern>/regist</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
[](javascript:void(0)😉
- 发布Web工程,并访问http://localhost:8080/jsp/index.jsp进行测试。
4.4. JSP动作标签
在JSP中可以像使用普通类一样访问JavaBean,JSP提供了三个动作标签jsp:useBean、jsp:setProperty和jsp:getProperty来访问JavaBean。
- jsp:useBean动作标签
该动作标签用于实例化JavaBean,或者定位一个已经存在的JavaBean实例。
该动作标签的语法格式:
<jsp:useBean id="实例名称" class="实例全类名" scope="指定范围"></jsp:useBean>
-
- id属性:用于标识JavaBean实例的名称。需要注意的是,指定的名称是区分大小写的,并遵照Java语言变量命名的约定。
- class属性:指定JavaBean实例的完整类名。
- scope属性:指定一个范围,在这个范围中,JavaBean实例的引用是可用的,实际上也是指定JavaBean实例的生命周期。备选取值有page、request、session和application,默认值为page。
jsp:useBean动作标签的实际作用可以利用下述Java代码进行解释:
[](javascript:void(0)😉
<jsp:useBean id="user" class="app.java.bean.User" scope="session" />
User user = (User)session.getAttribute("user");
if(user == null) {
user = new User();
session.setAttribute("user", user);
}
[](javascript:void(0)😉
- jsp:setProperty动作标签
该动作标签与jsp:useBean一起使用,用于设置JavaBean的属性。
该动作标签的语法格式:
<jsp:setProperty property="属性名称" name="实例名称" value="属性值"/>
- jsp:getProperty动作标签
该动作标签用于访问一个Bean的属性,并把属性的值转化成一个String,然后发送到输出流中。如果属性是一个对象,将调用该对象的toString()方法。
该动作标签的语法格式:
<jsp:getProperty property="属性名称" name="实例名称"/>
5. EL表达式语言
5.1. EL表达式语法
JSP中可以使用EL(Expression Language)表达式。EL表达式是用“${}”括起来的脚本,用来更方便地读取对象。EL表达式写在JSP的HTML代码中,而不能写在“<%%>”的JSP脚本中。
如果在JSP页面中使用了<%@ page isELIgnored=”true”%>指令的话,该JSP页面会忽略EL表达式。如果忽略某个EL表达式的话,可以在EL表达式之前添加“\”(例如${1+2})。
当EL表达式的值为null时,会在JSP页面上显示空白,即什么都不显示。
EL表达式具有一些运算符,如下表
运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
+ | 加 | ${17+5} | 22 |
- | 减 | ${17-5} | 12 |
* | 乘 | ${17*5} | 85 |
/或div | 除 | 17 / 5 或 {17/5}或 17/5或{17 div 5} | 3 |
%或mod | 取余 | KaTeX parse error: Expected '}', got 'EOF' at end of input: {17%5}或{17 mod 5} | 2 |
==或eq | 等于 | 5 = = 5 或 {5==5}或 5==5或{5 eq 5} | true |
!=或ne | 不等于 | 5 ! = 5 或 {5!=5}或 5!=5或{5 ne 5} | false |
<或lt | 小于 | 3 < 5 或 {3<5}或 3<5或{3 lt 5} | true |
>或gt | 大于 | 3 > 5 或 {3>5}或 3>5或{3 gt 5} | false |
<=或le | 小于等于 | 3 < = 5 或 {3<=5}或 3<=5或{3 le 5} | true |
>=或ge | 大于等于 | 3 > = 5 或 {3>=5}或 3>=5或{3 ge 5} | false |
&&或and | 并且 | KaTeX parse error: Expected '}', got '&' at position 6: {true&̲&false}或{true and false} | false |
!或not | 非 | ! t r u e 或 {!true}或 !true或{not true} | false |
||或or | 或者 | t r u e ∥ ∥ f a l s e 或 {true\|\|false}或 true∥∥false或{true or false} | true |
empty | 是否为空 | e m p t y “ ” , 可 以 判 断 字 符 串 、 数 据 、 集 合 的 长 度 是 否 为 0 , 为 0 返 回 t r u e 。 e m p t y 还 可 以 与 n o t 或 ! 一 起 使 用 。 {empty “”},可以判断字符串、数据、集合的长度是否为0,为0返回true。empty还可以与not或!一起使用。 empty“”,可以判断字符串、数据、集合的长度是否为0,为0返回true。empty还可以与not或!一起使用。{not empty “”} | true |
值得注意的是旧版本的Servlet规范不支持EL表达式,例如Tomcat 4.x以及以前的版本都不支持EL表达式。
EL表达式提供了获取JavaBean对象以及属性的简单方式。某些情况下EL表达式完全可以替代JSP脚本或者JSP行为,例如:
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'expression.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<jsp:useBean id="user" class="app.java.bean.User" scope="session" />
<!-- 相当于session.getArribute("person") -->
欢迎您,${person}.
<!-- 相当于person.getAge() -->
<!-- 也相当于<jsp:getProperty name="person" property="age"> -->
您的年龄为${person.age}.
</body>
</html>
[](javascript:void(0)😉
5.2. EL表达式内置对象
EL表达式不仅可以读取对象,还内置了十一个隐藏对象,这些内置对象无需创建,可以直接使用。而EL表达式中的内置对象中,最重要的是获取四大域相关的内置对象,如下表:
标识符 | 描述 | 示例 |
---|---|---|
pageScope | 包含apge作用域内变量的Map | 使用<jsp:useBean id=”user” class=”app.java.bean.User” scope=”page”>声明pageScope范围内的User对象后,${pageScope.user.name}将输出该对象的name属性值 |
requestScope | 包含request作用域内变量的Map | 使用<jsp:useBean id=”user” class=”app.java.bean.User” >声明requestScope范围内的User对象后,${requestScope.user.name}将输出该对象的name属性值。useBean标签默认的作用域为request |
sessionScope | 包含session作用域内变量的Map | 使用<jsp:useBean id=”user” class=”app.java.bean.User” scope=”session”>声明sessionScope范围内的User对象后,${sessionScope.user.name}将输出该对象的name属性值 |
applicationScope | 包含application作用域内变量的Map | 使用<jsp:useBean id=”user” class=”app.java.bean.User” scope=”applcation”>声明applcation Scope范围内的User对象后,${ applcation Scope.user.name}将输出该对象的name属性值 |
除了上述获取四大域相关的内置对象以外,还有其他内置对象,但实际使用率并不高。
类别 | 标识符 | 描述 | 示例 |
---|---|---|---|
请求参数 | param | 包含所有参数的Map,可以获取参数,返回String | p a r a m . f o o 或 {param.foo}或 param.foo或{param[‘foo’]} |
paramValues | 包含所有参数的Map,可以获取参数数组,返回String[] | 当提交多个参数,例如index.jsp?a=first&a=second,提交的参数a为多个值{“first”, “second”}。使用param只能获取第一个值,而使用paramValues能获取到所有值,${paramValues.a[0]}将输出“first”, ${paramValues.a[1]}将输出“second” | |
头信息 | header | 包含所有头信息的Map,返回String | ${header.host}可能返回localhost:8080 |
headerValues | 包含所有头信息的Map,返回String[] | ${headerValues.host[0]},当头信息为数组时可以获取多个值。 | |
初始化参数 | initParam | 包含所有初始化参数的Map | ${initParam.encoding} |
Cookie | cookie | 包含所有Cookie的Map,key为Cookie的name属性 | 使用<%response.addCookie(new Cookie(“user”, “king”))%>设置Cookie后, c o o k i e . u s e r 返 回 该 C o o k i e , {cookie.user}返回该Cookie, cookie.user返回该Cookie,{cookie.user.name}返回user,${cookie.user.value}返回king |
pageContext | 包含页面内的变量的Map,包含request、response、page等所有内置对象 | ${pageContext.request.remoteAddr}将返回客户端IP地址,相当于执行<%=pageContext.getRequest().getRemoteAddr()%> |
之前在页面中编写请求资源路径时,都是固定内容。在掌握了EL表达式后,可以如下方式编写请求资源路径:
<a href="${pageContext.request.contextPath }/index.jsp">请求</a>
5.3. EL表达式函数
EL函数库是由第三方对EL表达式的扩展,目前学习的EL函数库是由JSTL(关于JSTL会在后面的内容学到)添加的。EL函数库就是定义了一些有返回值的静态方法,然后通过EL表达式调用。当然不只是JSTL可以定义EL函数库,我们也可以自定义EL函数库。
因为EL函数库是第三方提供的,所有要想使用的话,首先需要使用taglib指令引入。
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
JSTL提供的EL函数库包含的函数具体如下:
- String toUpperCase(String input):将一个字符串转换成大写。
- String toLowerCase(String input):将一个字符串转换成小写。
- int indexOf(String input, String substring):检索字符串。
- boolean contains(String input, String substring):判断一个字符串是否包含另一个字符串。
- boolean containsIgnoreCase(String input, String substring):判断一个字符串是否包含另一个字符串(忽略大小写)。
- boolean startsWith(String input, String substring):判断一个字符串是否以另一个字符串开始。
- boolean endsWith(String input, String substring):判断一个字符串是否以另一个字符串结束。
- String substring(String input, int beginIndex, int endIndex):按照指定开始位置和结束位置截取字符串。
- String substringAfter(String input, String substring):截取指定字符后的所有字符串。
- String substringBefore(String input, String substring):截取指定字符前的所有字符串。
- String escapeXml(String input):将字符串内容进行转义。
- String trim(String input):将字符串的前后空格去掉。
- String replace(String input, String substringBefore, String substringAfter):将一个字符串中的某个字符,利用另一个字符替换。
- String[] split(String input, String delimiters):将一个字符串利用指定分隔符分割。
- int length(Object obj):返回指定内容的长度。
- String join(String array[], String separator):使用指定连接符将数组中的每个元素连接。
下面是上述函数的具体使用方式:
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'MyJsp.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<%
String[] strs = {"a", "b","c"};
List list = new ArrayList();
list.add("a");
pageContext.setAttribute("arr", strs);
pageContext.setAttribute("list", list);
%>
${fn:length(arr) }<br/><!--3-->
${fn:length(list) }<br/><!--1-->
${fn:toLowerCase("Hello") }<br/> <!-- hello -->
${fn:toUpperCase("Hello") }<br/> <!-- HELLO -->
${fn:contains("abc", "a")}<br/><!-- true -->
${fn:containsIgnoreCase("abc", "Ab")}<br/><!-- true -->
${fn:contains(arr, "a")}<br/><!-- true -->
${fn:containsIgnoreCase(list, "A")}<br/><!-- true -->
${fn:endsWith("Hello.java", ".java")}<br/><!-- true -->
${fn:startsWith("Hello.java", "Hell")}<br/><!-- true -->
${fn:indexOf("Hello-World", "-")}<br/><!-- 5 -->
${fn:join(arr, ";")}<br/><!-- a;b;c -->
${fn:replace("Hello-World", "-", "+")}<br/><!-- Hello+World -->
${fn:join(fn:split("a;b;c;", ";"), "-")}<br/><!-- a-b-c -->
${fn:substring("0123456789", 6, 9)}<br/><!-- 678 -->
${fn:substring("0123456789", 5, -1)}<br/><!-- 56789 -->
${fn:substringAfter("Hello-World", "-")}<br/><!-- World -->
${fn:substringBefore("Hello-World", "-")}<br/><!-- Hello -->
${fn:trim(" a b c ")}<br/><!-- a b c -->
${fn:escapeXml("<html></html>")}<br/> <!-- <html></html> -->
</body>
</html>
[](javascript:void(0)😉
我们也可以自定义EL函数库,具体自定义EL函数库的步骤如下:
- 创建一个Java类,该类包含具有返回值的静态方法。
[](javascript:void(0)😉
package app.java.el.functions;
public class MyFunctions {
public static String test() {
return "自定义EL函数库测试";
}
}
[](javascript:void(0)😉
- 在WEB-INF目录下创建一个“.tld”文件,用于配置自定义EL函数库。
[](javascript:void(0)😉
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>myfn</short-name>
<uri>http://www.myfn.com/jsp/functions</uri>
<function>
<name>test</name>
<function-class>app.java.el.functions</function-class>
<function-signature>String test()</function-signature>
</function>
</taglib>
[](javascript:void(0)😉
- 在JSP页面中添加tagllib指令,导入自定义EL函数库。
[](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="ls" uri="/WEB-INF/myfunctions.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>自定义EL函数库</title>
</head>
<body>
<h1>${ls:test() }</h1>
</body>
</html>
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd”
version=“2.0”>
1.0
myfn
http://www.myfn.com/jsp/functions
[[外链图片转存中…(img-O7v7tGpX-1644682260189)]](javascript:void(0)😉
- 在JSP页面中添加tagllib指令,导入自定义EL函数库。
[[外链图片转存中…(img-Sv7Bz5oD-1644682260189)]](javascript:void(0)😉
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="ls" uri="/WEB-INF/myfunctions.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>自定义EL函数库</title>
</head>
<body>
<h1>${ls:test() }</h1>
</body>
</html>
[](javascript:void(0)😉