目录
一、JSP指令
1.JSP指令概述
JSP指令的格式:<%@指令名 attr1=”” attr2=”” %>,一般都会把JSP指令放到JSP文件的最上方,但这不是必须的。
JSP中有三大指令:page、include、taglib,最为常用,也最为复杂的就是page指令了。
2.page指令
page指令是最为常用的指定,也是属性最多的属性!
page指令没有必须属性,都是可选属性。例如<%@page %>,没有给出任何属性也是可以的!
在JSP页面中,任何指令都可以重复出现!
<%@ page language=”java”%>
<%@ page import=”java.util.*”%>
<%@ page pageEncoding=”utf-8”%>
这也是可以的!
(1)pageEncoding和contentType
> pageEncoding:它指定当前jsp页面的编码。在服务器要把jsp编译成.java时需要使用pageEncoding!
> contentType:等同与response.setContentType("text/html;charset=utf-8")。
> 如果两个属性只提供一个,那么另一个的默认值为设置那一个。
> 如果两个属性都没有设置,那么默认为iso-8859-1。
(2)import
import是page指令中一个很特别的属性!
import属性值对应“真身”中的import语句。
import属性值可以使用逗号隔开:<%@page import=”java.net.*,java.util.*,java.sql.*”%>
import属性是唯一可以重复出现的属性:
<%@page import=”java.util.*” import=”java.net.*” import=”java.sql.*”%>
但是,我们一般会使用多个page指令来导入多个包:
<%@ page import=”java.util.*”%>
<%@ page import=”java.net.*”%>
<%@ page import=”java.text.*”%>
(3)errorpage和isErrorpage
我们知道,在一个JSP页面出错后,服务器会响应给用户错误信息(500页面)!如果你不希望Tomcat给用户输出错误信息,那么可以使用page指令的errorPage来指定错误页!也就是自定义错误页面,例如:<%@page errorPage=”xxx.jsp”%>。这时,在当前JSP页面出现错误时,会请求转发到xxx.jsp页面。
a.jsp
<%@ page import="java.util.*" pageEncoding="UTF-8"%>
<%@ page errorPage="b.jsp" %>
<%
if(true)
throw new Exception("哈哈~");
%>
b.jsp
<%@ page pageEncoding="UTF-8"%>
<html>
<body>
<h1>出错啦!</h1>
</body>
</html>
在上面代码中,a.jsp抛出异常后,会请求转发到b.jsp。在浏览器的地址栏中还是a.jsp,因为是请求转发!
而且客户端浏览器收到的响应码为200,表示请求成功!如果希望客户端得到500,那么需要指定b.jsp为错误页面。
<%@ page isErrorPage="true"%>
注意:当isErrorPage为true时,说明当前JSP为错误页面,即专门处理错误的页面。那么这个页面中就可以使用一个内置对象exception了。其他页面是不能使用这个内置对象的!
(4)web.xml中配置错误页面
不只可以通过JSP的page指令来配置错误页面,还可以在web.xml文件中指定错误页面。
web.xml
<error-page>
<error-code>404</error-code>
<location>/error404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error500.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/error.jsp</location>
</error-page>
<error-code>是指定响应码;
<location>指定转发的页面;
<exception-type>是指定抛出的异常类型。
在上例中:
当出现404时,会跳转到error404.jsp页面;
当出现RuntimeException异常时,会跳转到error.jsp页面;
当出现非RuntimeException的异常时,会跳转到error500.jsp页面。
(5)autoFlush和Buffer
> autoFlush:指定jsp的输出流缓冲区满时,是否自动刷新!默认为true,如果为false,那么在缓冲区满时抛出异常!
> buffer:指定缓冲区大小,默认为8kb,通常不需要修改!
(6)isELIgnored
是否忽略el表达式,默认值为false,不忽略,即支持!
(7)page指令的其他属性
> language:指定当前jsp编译后的语言类型,默认值为java。
> info:jsp说明性信息!
> isThreadSafe:当前的jsp是否支持并发访问!
> session:当前页面是否支持session,如果为false,那么当前页面就没有session这个内置对象!
> extends:让jsp生成的servlet去继承该属性指定的类!
3.include指令
include指令表示静态包含!即目的是把多个JSP合并成一个JSP文件!
include指令只有一个属性:file,指定要包含的页面,例如:<%@include file=”b.jsp”%>。
静态包含:当hel.jsp页面包含了lo.jsp页面后,在编译hel.jsp页面时,需要把hel.jsp和lo.jsp页面合并成一个文件,然后再编译成Servlet(Java文件)。
4.taglib指令
在JSP页面中使用第三方的标签库时,需要使用taglib指令来“导包”。例如:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
其中prefix表示标签的前缀,这个名称可以随便起。uri是由第三方标签库定义的,所以你需要知道第三方定义的uri。
二、JSP九大内置对象
1.JSP九大内置对象
在JSP中无需创建就可以使用的9个对象,它们是:
out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
config(ServletConfig):对应“真身”中的ServletConfig;
page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象;
pageContext(PageContext):页面上下文对象;
exception(Throwable):只有在错误页面中可以使用这个对象;
request(HttpServletRequest):即HttpServletRequest类的对象;
response(HttpServletResponse):即HttpServletResponse类的对象;
application(ServletContext):即ServletContext类的对象;
session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。
2.pageContext对象
在JavaWeb中一共四个域对象,其中Servlet中可以使用的是request、session、application三个对象,而在JSP中可以使用pageContext、request、session、application四个域对象。
pageContext 对象是PageContext类型,它的主要功能有:
域对象功能;
代理其它域对象功能;
获取其他内置对象;
(1)域对象功能
pageContext也是域对象,它的范围是当前页面。它的范围也是四个域对象中最小的!
void setAttribute(String name, Object value);
Object getAttrbiute(String name, Object value);
void removeAttribute(String name, Object value);
(2)代理其他域对象功能
可以使用pageContext向request、session、application对象中存取数据
void setAttribute(String name, Object value, int scope):在指定范围中添加数据;
Object getAttribute(String name, int scope):获取指定范围的数据;
void removeAttribute(String name, int scope):移除指定范围的数据;
Object findAttribute(String name):依次在page、request、session、application范围查找名称为name的数据,如果找到就停止查找。
<%
//向pageContext中存储数据
pageContext.setAttribute("x", "X");
//向request中存储数据
pageContext.setAttribute("x", "XX",PageContext.REQUEST_SCOPE);
//向session中存储数据
pageContext.setAttribute("x", "XXX",PageContext.SESSION_SCOPE);
//向application中存储数据
pageContext.setAttribute("x", "XXXX",PageContext.APPLICATION_SCOPE);
%>
(3)获取其他内置对象
一个pageContext对象等于所有内置对象。这是因为可以使用pageContext对象获取其它8个内置对象:
JspWriter getOut():获取out内置对象;
ServletConfig getServletConfig():获取config内置对象;
Object getPage():获取page内置对象
ServletRequest getRequest():获取request内置对象;
ServletResponse getResponse():获取response内置对象;
HttpSession getSession():获取session内置对象;
ServletContext getServletContext():获取application内置对象;
Exception getException():获取exception内置对象;
三、JavaBean
1.JavaBean概述
JavaBean是一种规范,也就是对类的要求。它要求Java类的成员变量提供getter/setter方法,这样的成员变量被称之为JavaBean属性。
JavaBean还要求类必须提供仅有的无参构造器,例如:public User() {…}
2.JavaBean属性
JavaBean属性是具有getter/setter方法的成员变量。
也可以只提供getter方法,这样的属性叫只读属性;
也可以只提供setter方法,这样的属性叫只写属性;如果属性类型为boolean类型,那么读方法的格式可以是get或is。例如名为abc的boolean类型的属性,它的读方法可以是getAbc(),也可以是isAbc();
注意:
(1)JavaBean属性名要求:前两个字母要么都大写,要么都小写:
private String iD; //错误的JavaBean属性
(2)JavaBean可能存在属性,但不存在这个成员变量
public class User {
public String getUsername() {
return "zhangSan";
}
}
该User类有一个Username的只读属性,但并没有Username这个成员变量
3.内省
内省的目标是得到JavaBean属性的读、写方法的反射对象,通过反射对JavaBean属性进行操作的一组API。例如User类有名为username的JavaBean属性,通过两个Method对象(一个是getUsername(),一个是setUsername())来操作User对象。
(1)内省之获取BeanInfo
通过java.beans.Introspector的getBeanInfo()方法来获取java.beans.BeanInfo实例。
BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
(2)得到所有属性描述符(PropertyDescriptor)
通过BeanInfo可以得到这个类的所有JavaBean属性的PropertyDescriptor对象。然后就可以通过PropertyDescriptor对象得到这个属性的getter/setter方法的Method对象了。
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
每个PropertyDescriptor对象对应一个JavaBean属性:
String getName():获取JavaBean属性名称;
Method getReadMethod:获取属性的读方法;
Method getWriteMethod:获取属性的写方法。
(3)完成Map数据封装到User中
@Test
public void fun1() throws Exception {
Map<String, String> map = new HashMap<String, String>();
map.put("username", "admin");
map.put("password", "admin123");
BeanInfo beanInfo = Introspector.getBeanInfo(User.class);// 获取User类型的BeanInfo实例
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();// 获取User类型的所有JavaBean属性的属性描述符对象
User user = new User();// 创建User实例
// 循环遍历每个属性描述符对象
for (PropertyDescriptor pd : pds) {
String name = pd.getName();// 获取JavaBean属性名
String value = map.get(name);// 获取Map中对应属性的值
// 如果在Map中存在这个属性的值
if (value != null) {
Method writeMethod = pd.getWriteMethod();// 获取该属性的写方法
writeMethod.invoke(user, value);// 把Map中的值写入到user对象的对应属性中
}
}
System.out.println(user);
}
4.commons-beanutils
它底层使用了内省,对内省进行了大量的简化!
使用beanutils需要的jar包:
commons-beanutils.jar;
commons-logging.jar
(1)设置JavaBean属性
User user = new User();
BeanUtils.setProperty(user, "username", "admin");
BeanUtils.setProperty(user, "password", "admin123");
System.out.println(user);
(2)获取JavaBean属性
User user = new User("admin", "admin123");
String username = BeanUtils.getProperty(user, "username");
String password = BeanUtils.getProperty(user, "password");
System.out.println("username=" + username + ", password=" + password);
(3)封装Map到JavaBean对象中
Map<String, String> map = new HashMap<String, String>();
map.put("username", "admin");
map.put("password", "admin123");
User user = new User();
// 把map中的数据封装到user对象中,要求user的属性名要与map的key一致。
BeanUtils.populate(user, map);
System.out.println(user);
5.JSP与JavaBean相关的动作标签
在JSP中与JavaBean相关的标签有:
<jsp:useBean>:创建JavaBean对象;
<jsp:setProperty>:设置JavaBean属性;
<jsp:getProperty>:获取JavaBean属性;
(1)<jsp:useBean>
<jsp:useBean id="user1" class="cn.yfy_01.User" />
上面代码表示在当前JSP页面中创建User类型的对象,并且把它保存到page域中了。
可以通过scope标签属性来指定保存的范围:
<jsp:useBean id="user2" class="cn.yfy_01.User" scope="request"/>
注意:<jsp:useBean>标签其实不一定会创建对象!!!它会先在指定范围中查找这个对象,如果对象不存在才会创建。
(2)<jsp:setProperty>和<jsp:getProperty>
<jsp:setProperty>标签的作用是给JavaBean设置属性值,而<jsp:getProperty>是用来获取属性值。在使用它们之前需要先创建JavaBean:
<jsp:useBean id="user1" class="cn.yfy_01.User" />
<jsp:setProperty property="username" name="user1" value="admin"/>
<jsp:setProperty property="password" name="user1" value="admin123"/>
用户名:<jsp:getProperty property="username" name="user1"/><br/>
密 码:<jsp:getProperty property="password" name="user1"/><br/>
四、EL表达式
1.EL概述
(1)EL的作用
JSP2.0要把html和css分离、要把html和javascript分离、要把Java脚本替换成标签。标签的好处是非Java人员都可以使用。
JSP2.0 – 纯标签页面,即:不包含<% … %>、<%! … %>,以及<%= … %>
EL(Expression Language)是一门表达式语言,它对应<%=…%>。我们知道在JSP中,表达式会被输出,所以EL表达式也会被输出。
(2)关闭EL
如果希望整个JSP忽略EL表达式,需要在page指令中指定isELIgnored=”true”。
如果希望忽略某个EL表达式,可以在EL表达式之前添加“\”,例如:\${1 + 2}。
(3)EL运算符
2.EL表达式格式
操作List和数组:${list[0]}、${arr[0]};
操作bean的属性:${person.name}、${person[‘name’]},对应person.getName()方法;
操作Map的值:${map.key}、${map[‘key’]},对应map.get(key)。
3.EL内置对象(11个)
(1)四个域相关内置对象
pageScope:${pageScope.name}等同与pageContext.getAttribute(“name”);
requestScope:${requestScope.name}等同与request.getAttribute(“name”);
sessionScope: ${sessionScope.name}等同与session.getAttribute(“name”);
applicationScope:${applicationScope.name}等同与application.getAttribute(“name”);
如果在域中保存的是JavaBean对象,那么可以使用EL来访问JavaBean属性。因为EL只做读取操作,所以JavaBean一定要提供get方法,而set方法没有要求。
${requestScope.emp.address.street }
等同于request.getAttribute("emp").getAddress().getStreet()
全域查找:${person}表示依次在pageScope、requesScopet、sessionScope、appliationScope四个域中查找名字为person的属性。
(2)两个请求参数相关内置对象
param和paramValues这两个内置对象是用来获取请求参数的。
param:Map<String,String>类型,param对象可以用来获取参数。
paramValues:Map<String, String[]>类型,当一个参数名,对应多个参数值时可以使用它。
注意:在使用EL获取参数时,如果参数不存在,返回的是空字符串,而不是null。这一点与使用request.getParameter()方法是不同的。
(3)两个请求头相关内置对象
header和headerValues是与请求头相关的内置对象:
header: Map<String,String>类型,用来获取请求头。
headerValues:Map<String,String[]>类型。当一个请求头名称,对应多个值时,使用该对象。
(4)应用初始化参数相关内置对象
initParam:Map<String,String>类型。它对应web.xml文件中的<context-param>参数。
(5)Cookie相关内置对象
cookie:Map<String,Cookie>类型,其中key是Cookie的名字,而值是Cookie对象本身。
(6)pageContext对象
pageContext:pageContext是PageContext类型!可以使用pageContext对象调用getXXX()方法,获取其他内置对象。
${pageContext.request.contextPath}
等同于pageContext.getRequest().getContextPath()
五、EL函数库
1.什么是EL函数库
EL函数库是由第三方对EL的扩展,EL函数库是由JSTL添加的。
EL函数库就是定义一些有返回值的静态方法。然后通过EL语言来调用它们!当然,不只是JSTL可以定义EL函数库,我们也可以自定义EL函数库。
EL函数库中包含了很多对字符串的操作方法,以及对集合对象的操作。例如:${fn:length(“abc”)}会输出3,即字符串的长度。
2.函数库的导入
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
3.上面fn函数库的常见方法
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):获取大串中,小串所在位置后面的字符串
substringBefore(String input, String substring):获取大串中,小串所在位置前面的字符串
String escapeXml(String input):把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):联合字符串数组!
4.自定义函数库
写一个类,写一个有返回值的静态方法;
编写itcast.tld文件,可以参考fn.tld文件来写,把itcast.tld文件放到/WEB-INF目录下;
在页面中添加taglib指令,导入自定义标签库。
package cn.yfy.el.function;
public class Test {
public static String show(){
return "骑士总冠军";
}
}
<?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">
<description>yfy</description>
<display-name>yfy-function</display-name>
<tlib-version>1.0</tlib-version>
<short-name>fy</short-name>
<uri>http://java.yfy.com/jsp/jstl/functions</uri>
<function>
<name>show</name>
<function-class>cn.yfy.el.function.Test</function-class>
<function-signature>java.lang.String show()</function-signature>
</function>
</taglib>
<%@ taglib prefix="fy" uri="http://java.yfy.com/jsp/jstl/functions" %>
<body>
<h1>${fy:show()}</h1>
</body>