JSP简介
(表示层技术)
1.什么是JSP
sun公司制定的一种服务器端的动态页面技术规范(sun公司被Oracle公司收购了)
注:生成动态页面,只需要写一个以".jsp"为后缀名的文件,该文件会被容器自动转换成一个对应的Servlet然后执行。也就是说,JSP
本质就是一个Servlet
!
(可在tomcat的安装目录下查看work目录下的D:\JavaDevTools\apache-tomcat-9.0.30\work\Catalina\localhost\jspdemo\org\apache\jsp
)
2.如何写一个JSP?
1. 添加一个以.jsp
为后缀的文件
2. 在该文件里面,可以使用如下几个元素:
-
html(css,javascript)
直接写即可 -
java代码
-
方式一:java代码片段
<% java代码 %>
time:<% Date date = new Date(); out.print(date); %>
-
方式二:jsp表达式
<%= java表达式 %>
time:<%= new Date() %>
-
方式三:jsp声明
<%! 声明变量或者方法 %>
<%! String info = "您好"; %> <%= info> <%! int sum(int a,int b){ return a + b; } %> <%= sum(2,4) %> // 这个编译成.java文件就是一个成员变量或者方法,它不在service方法中!!!
-
-
隐含对象(内置对象)
-
什么是隐含对象?
直接可以使用的对象,比如out、request和response。 out = pageContext.getOut();
-
为什么可以直接使用这些隐含对象?
容器会自动添加获得这些对象的代码。
-
有哪些隐含对象?
session:HttpSession接口的实现,也就是session对象。 //javax.servlet.http.HttpSession session = null; //session = pageContext.getSession(); application:ServletContext接口的实现,也就是Servlet上下文。 //注:容器启动之后,会为每一个web应用(比如jspdemo)创建唯一的一个符合ServletContext接口要求的对象,该对象称之为Servlet上下文。该对象会一直存在,除非容器关闭或者应用被删除 //final javax.servlet.ServletContext application; // application = pageContext.getServletContext(); // 全局共享的,都可以访问 pageContext:PageContext接口的实现,也就是页面上下文 //注:容器会为每一个JSP实例创建唯一的一个符合PageContext接口要求的对象,该对象称之为页面上下文。该对象会一直存在,除非JSP实例被销毁。pageContext提供了一些用来获得其他所有的隐含对象的方法(用于JSP标签,JSP标签类可以通过该对象来访问到其他隐含对象) // 一个JSP实例对应一个pageContext(页面上下文) // pageContext会一直存在,除非JSP实例被删除 // 注:绑定到pageContext上的数据只有与之对应的jsp实例能够访问到。 config:ServletConfig接口的实现。 // 注:可以通过该对象读取初始化参数。 // final javax.servlet.ServletConfig config; // config = pageContext.getServletConfig(); exception:用来获得JSP运行时产生的异常信息的 // 注:只有当page指令的isErrorPage属性值为true时,才能使用该隐含对象 page(从来不用的,了解):JSP实例本身 注意:JSP实例指的是JSP对应的Servlet实例
-
示例:
示例:
```jsp
<%@ page contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<html>
<head>
<title></title>
</head>
<body style="font-size:30px">
<!-- 隐藏对象session -->
sessionId: <%= session.getId() %>
<!-- 隐藏对象application -->
<%
application.setAttribute("username", "林龙");
%>
username:<%= application.getAttribute("username") %>
<!-- 隐藏对象config -->
<!-- 先在web.xml中配置servlet,然后就可以通过config.get方法来获取了
<servlet>
<servlet-name>test7</servlet-name>
<jsp-file>/test7.jsp</jsp-file>
<init-param>
<param-name>company</param-name>
<param-value>某公司</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>test7</servlet-name>
<url-pattern>/test.html</url-pattern>
</servlet-mapping> -->
公司名:<%= config.getInitParameter("company") %>
</body>
</html>
```
示例exception:
test8.jsp
```jsp
<%@ page contentType="text/html; charset=utf-8"
pageEncoding="utf-8" errorPage="test9.jsp" %>
<html>
<head>
<title></title>
</head>
<body style="font-size:30px">
<%
String number = request.getParameter("number");
int number1 = Integer.parseInt(number);
out.print(number1 * 2);
%>
</body>
</html>
```
test9.jsp
```jsp
<%@ page contentType="text/html; charset=utf-8"
pageEncoding="utf-8" isErrorPage="true" %>
<html>
<head>
<title></title>
</head>
<body style="font-size:30px">
请输入合法的数字!
<%= exception.getMessage() %>
</body>
</html>
```
-
指令
-
什么是指令?
通知容器,在将JSP转换成对应的Servlet时做一些额外的处理,比如导包。
-
语法格式
<%@ 指令名 属性=值 %>
-
page指令
import属性:用于指定要导的包名,比如:
<%@ page import="java.util.*"%> <%@ page import="java.util.* , java.text.*"%>
contentType属性:用于设置response.setContentType方法的 MIME类型。
pageEncoding属性:用于设置JSP文件的编码(保存在硬盘上)。
(如果不加的话,部分容器是默认使用ISO8859-1来编码)
<%@ page import="java.util.*" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
errorPage属性:指定一个异常处理页面。当JSP运行时发生了异常,则容器会调用异常处理页面来处理。
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" errorPage="test9.jsp" %> <html> <head> <title></title> </head> <body style="font-size:30px"> <% String number = request.getParameter("number"); // 这里类型转换时会发生异常 int number1 = Integer.parseInt(number); out.print(number1 * 2); %> </body> </html>
isErrorPage属性:缺省值是false,当值为true时,表示这是一个异常处理页面。
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" isErrorPage="true" %> <html> <head> <title></title> </head> <body style="font-size:30px"> 请输入合法的数字! <%= exception.getMessage() %> </body> </html>
session属性:缺省值是true,如果值为false,则session隐含对象就不能使用了。
注:如果系统不再使用原生的session,建议将些属性设置为false。<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" session="false"%> <html> <head> <title></title> </head> <body style="font-size:30px"> sessionId: <%= session.getId() %> <!-- 如果设置为false的话,这行会保错,编译失败 --> </body> </html>
在一些特定的情况,有必要设置为false。如果把session设置到redis中,那么原生的session就不需要了
(即当系统不需要原生的session)
-
- include指令
file属性:指定一个被包含的文件名。include指令用来通知容器在将JSP转换成Servlet时,将file属性所指定的文件的内容插入到该指令所在的位置。
注:被包含的文件如果是JSP,则该JSP不会执行。被包含的文件只负责提供内容。
示例:
index.jsp
<div id="top_content">
<%@ include file="/WEB-INF/header.jsp" %>
<div id="content">
</div>
header.jsp
<%@ page import="java.util.* , java.text.*" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" %>
<div id="header">
<div id="rightheader">
<p>
<%
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
String str = sdf.format(now);
out.print(str);
%>
<br />
</p>
</div>
<div id="topheader">
<h1 id="title">
<a href="#">main</a>
</h1>
</div>
<div id="navigation">
</div>
</div>
- e.taglib 指令
用于导入JSP标签,具体用法参见JSP标签。
3.JSP是如何执行的?
-
阶段一:容器将JSP转换成一个对应的Servlet。
a. html(css,js) --------> 在service方法里,使用out.write输出。 b. <% %> --------->照搬到service方法里面。 c. <%= %> --------->在service方法里,使用out.print输出。 d. <%! %>----------->添加新的成员变量或者方法
示例:
out.write("\r\n"); out.write("<html>\r\n"); out.write("\t<head></head>\r\n"); out.write("\t<body style=\"font-size:30px;\">\r\n"); out.write("\t\t加油!\r\n"); out.write("\t\ttime:"); out.print( new Date() ); out.write("\r\n"); out.write("\t\t<br />\r\n"); out.write("\t\ttime:"); Date date = new Date(); out.print(date); out.write("\r\n"); out.write("\t\t<br />\r\n"); out.write("\t\tHello JSP!\r\n"); out.write("\t\t"); for(int i=0;i<100;i++){ out.print("Hello JSP <br />"); }
-
阶段二:容器调用该Servlet。
注:容器会将这个Servlet进行编译,然后实例化、初始化,最后调用其方法(service方法)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WmabIu8H-1583583934952)(C:/Users/雪麟锋/Downloads/day02_all/a0.png)]
示例1:写一个Date.jsp,输出当前的系统日期,比如输出2020年02月22日
<%@ page import="java.util.*, java.text.*" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %> <html> <head></head> <body style="font-size:30px;"> 系统当前时间是: <% Date now = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String str = sdf.format(now); out.print(str); %> </body> </html>
示例2:写一个“用户列表”,即将用户表中的所有用户信息以表格的形式来展现。
<%@ page import="java.util.* ,dao.*, entity.*" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %> <html> <head> <style> .row1{ background-color:#0f0; } .row2{ background-color:#f0f; } </style> </head> <body style="font-size:30px"> <table border="1" width="60%" cellpadding="0"> <tr> <td>ID</td> <td>姓名</td> <td>密码</td> <td>邮箱</td> </tr> <% UserDAO dao = new UserDAO(); List<User> users = dao.findAll(); for(int i=0;i<users.size();i++){ User user = users.get(i); %> <tr class="row<%= i%2+1%>"> <td><%= user.getId() %></td> <td><%= user.getUsername() %></td> <td><%= user.getPwd() %></td> <td><%= user.getEmail() %></td> </tr> <% } %> </table> </body> </html>
4.转发
-
什么是转发?
一个web组件将未完成的处理交给另外一个web组件继续做。
- web组件是Servlet和JSP的统称
- 常用的场景是Servlet获取数据之后转发给JSP,由JSP来展现
- 如何转发
step1.将数据绑订到request对象上。
request.setAttribute(String name,Object obj);
注:
绑订的本质就是map.put(name,obj);
Object request.getAttribute(String name);
step2.获得转发器。
RequestDispatcher rd = request.getRequestDispatcher(String uri);
注:
RequestDispatcher是一个接口,该方法会返回一个符合该接口要求的对象,我们称之为转发器。
uri是转发的地址,一般是一个JSP。
step3.转发
rd.forward(request,response);
-
转发与重定向的区别
-
能否共享request对象?
转发可以,而重定向不行。
注:容器收到请求之后,会立即创建request和response,当响应发送完毕,会立即销毁这两个对象。也就是说,request和response对象的生存时间是一次请求与响应期间存在。
-
浏览器地址栏的地址有无变化?
转发没有变化,而重定向有变化。
-
地址有无限制?
转发有限制,要求属于同一个web应用,而重定向没有任何限制。
-
一件事是否已经做完?
转发是一件事没有做完,让另外一个web组件继续做;而重定向是一件事已经完成,然后再做另外一件独立的事情。
-
5. JSP标签和EL表达式
(1)什么是JSP标签
一种用于替换JSP中java代码的技术,语法类似于html,比如有开始标记、结束标记、有一些属性、有标签体。
注:
使用JSP标签,方便JSP文件的维护(比如将带有java代码的JSP文件直接交给美工去修改就很不方便),另外,也方便代码的复用(比如可以将一些通用的java代码封装成JSP标签,在不同的应用当中可以复用)。
(2)什么是EL表达式?
是一套简单的运算规则,用于给JSP标签的属性赋值。
注:
EL表达式也可以脱离JSP标签,直接使用。
(3)EL表达式的使用
- 读取bean的属性:
方式一: ${e.ename}
1. 执行过程:容器会依次从pageContext–>request–>session–>application中查找绑订名为"e"的对象,然后调用该对象的"getEname"方法,最后输出该方法的返回结果。
注:如果依据绑订名找不到对应的对象,不会报空指针异常,会输出“”。
2. EL表达式的优点:
相对于直接写java代码,要更加简洁。
会将null转换成""输出。
3. 可以使用pageScope、requestScope、sessionScope、applicationScope来指定查找的范围。
方式二:${e[‘ename’]}
- [ ]里面可以出现绑订名。
- [ ]里面可以出现从0开始的下标,用于访问数组中指定下标处的某个元素。
<%@ page import="bean.*" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<html>
<head>
<title></title>
</head>
<body style="font-size:30px">
<%
Employee e = new Employee();
e.setEname("林龙");
e.setGender("m");
e.setCity(new String[]{"北京","上海"});
request.setAttribute("e", e);
Employee e2 = new Employee();
e2.setEname("林玲");
e2.setGender("g");
session.setAttribute("e", e2);
%>
姓名:
<%
Employee e1 = (Employee)request.getAttribute("e");
out.print(e1.getEname());
%>
<br>
姓名:${e.ename} <!-- 林龙 -->
<br>
姓名(session范围的):${sessionScope.e.ename}; <!-- 林玲 -->
<br>
姓名(用[]表示):${e['ename']} <!-- 林龙 -->
<br>
<%
request.setAttribute("s1", "ename");
%>
姓名(el绑定名形式):${e[s1]} <!-- 林龙 -->
<br>
测试(无输出的):${e[requestScope.s1]} <!-- 这种是找不到的,没有输出,因为requestScope没有s1 -->
测试(无输出的):${e[sessionScope.s1]} <!-- 这种是找不到的,没有输出,因为sessionScope没有s1 -->
<br>
城市:${e.city} <!-- 这样输出的数组是无意义的,输出的是[Ljava.lang.String;@56f7a82d -->
<br>
城市(0下标):${e.city[0]} <!-- 北京 -->
</body>
</html>
- 做一些简单的运算。
-
算术运算
+ 、-、*、/、% 注: " + " 只能求和。
-
.关系运算
>、>=、<、<=、==、!=
-
逻辑运算
&&、||、!
-
empty运算
empty运算用来判断集合是否为空,或者是否为一个空字符串。
示例:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" import="java.util.*" %> <html> <head> <title></title> </head> <body style="font-size:30px"> 算数运算:${1+1} <br> <!-- 不能进行字符串的拼接操作(如"a"+"b",转换不了数字) --> ${"1" + "1" } <!-- 这样是可以的,会自动转换成数字进行加法运算 --> <br> 关系运算:${1<2}<br> <!-- true --> <% pageContext.setAttribute("s1", "abc"); %> ${s1 == "abc" }<br> <!-- true --> ${pageScope.s1 == "abc" }<br> <!-- true --> 逻辑运算:${1<2 && 3>4}<br> <!-- false --> empty运算:<br> <% List<String> list = new ArrayList<>(); pageContext.setAttribute("list", list); pageContext.setAttribute("s2", ""); %> ${empty list}<br> <!-- 因为是个空集合,所以是true --> ${empty s2}<br> <!-- 因为是个空字符串,所以是true --> ${empty aaa}<br> <!-- 因为aaa不存在,所以是true --> </body> </html>
- 读取请求参数值
-
${param.username}等价于
String username = request.getParameter(“username”); -
${paramValues.city}等价于
String[] city = request.getParameterValues(“city”);
注:当有多个请求参数名相同时,使用此方法。
示例:<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <html> <head> <title></title> </head> <body style="font-size:30px"> java代码获取参数 <% String username = request.getParameter("username"); %> username: <%= username %> <!-- 没有传参时输出null --> <br> 用el表达式,跟上面是等效的 username: ${param.username } <!-- 没有传参时输出空字符串 --> <br> <!-- http://localhost:8080/jspdemo/el03.jsp?city=bj&city=sh&city=cc --> <% String[] city = request.getParameterValues("city"); %> city[0]:<%= city[0] %> <br> 用el表达式输出city[0]:${paramValues.city[0]} <br> </body> </html>
JSTL
(1)JSTL是什么?
JSTL(jsp standard tag lib): JSP标准标签库。是由apache开发的一套JSP标签,后来捐献给了SUN,SUN将其命名为JSTL。
(2)如何使用JSTL?
step1.导入JSTL相关的jar包(在pom.xml中)。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
step2.使用taglib指令导入要使用的具体的标签。
<%@ taglib uri="" prefix=""%>
uri属性:指定要导入的JSP标签所属的命名空间。
注:
命名空间是为了区分同名的元素而在元素前添加的一段说明,通常是一个域名(为了避免命名空间的冲突)。
prefix属性:用来指定命名空间的别名。
<%@ page contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="bean.*" %>
<!-- 标签所属的命名空间 -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
(3)几个核心的标签:
- if标签
<c:if test="">
标签体
</c:if>
用法:
当test属性值为true时,执行标签体的内容。
test属性可以使用el表达式来赋值。
示例:
<%@ page contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="bean.*" %>
<!-- 标签所属的命名空间 -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title></title>
</head>
<body style="font-size:30px">
<%
Employee e = new Employee();
e.setEname("小鱼儿");
e.setGender("m");
request.setAttribute("e", e);
%>
姓名:${e.ename} <br>
<!-- 将m转换成用户能够识别的"男" -->
性别:<c:if test="${e.gender=='m'}">男</c:if> <br>
</body>
</html>
- 标签的执行过程:
容器依据标签的命名空间找到标签的描述文件(.tld文件),然后依据标签名找到对应的标签类,然后将该标签类实例化,最后调用标签实例的方法。
- choose标签
<c:choose>
<c:when test="">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
用法:
when可以出现1次或者多次,相当于一个if语句,当test属性值为true时,执行标签体的内容。
otherwise可以出现0次或者1次,相当于最后那个else语句。
示例:
<%@ page contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="bean.*"%>
<!-- 标签所属的命名空间 -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title></title>
</head>
<body style="font-size:30px">
<%
Employee e = new Employee();
e.setEname("小鱼儿");
e.setAge(66);
e.setGender("w");
request.setAttribute("e", e);
%>
性别:<c:choose>
<c:when test="${e.gender=='m'}">男</c:when>
<c:when test="${e.gender=='f'}">女</c:when>
<c:otherwise>保密</c:otherwise>
</c:choose>
<br>
${e.ename},${e.age }:
<c:choose>
<c:when test="${e.age<18}">未成年</c:when>
<c:when test="${e.age>60}">老年</c:when>
<c:otherwise>成年</c:otherwise>
</c:choose>
</body>
</html>
- forEach标签
<c:forEach items="" var="" varStatus="">
</c:forEach>
用法:
items属性用于指定要遍历的集合或者数组,可以使用EL表达式来赋值。
var属性用于指定一个绑订名。
注:该标签每次从items属性所指定的集合或者数组中取一个元素,然后将其绑订到pageContext上,绑订名由var属性来指定。
varStatus属性用于指定一个绑订名。
注:该标签会创建一个特殊的对象,并且将该对象绑订到了pageCOntext上。这个特殊对象提供了一些用于获得当前遍历状态的方法:
getIndex():获得当前正在被遍历的元素的下标(从0开始)。
getCount():获得遍历的次数(即正在取第几个元素,从1开始)。
示例:
// ActionServlet.java(req.setAttribute("users",users))
if("/list.do".equals(path)) {
// 调用业务层代码,业务层在调用DAO模型层,这里直接调用DAO
UserDAO dao = new UserDAO();
List<User> users = dao.findAll();
// 依据模型返回的结果,调用对应的视图处理
req.setAttribute("users", users);
RequestDispatcher rd = req.getRequestDispatcher("/WEB-INF/listUsers3.jsp");
rd.forward(req, resp);
}
<c:forEach items="${users}" var="user" varStatus="s">
<tr class="row${s.index % 2 + 1}">
<td>
${user.id}
</td>
<td>
${user.username}
</td>
<td>
${user.pwd}
</td>
<td>
${user.email}
</td>
<td>
<a href="listUsers.html">删除</a>
</td>
<td>
${s.index}<!-- 下标从0开始 -->
</td>
<td>
${s.count}<!-- 序号从1开始 -->
</td>
</tr>
</c:forEach>
示例:
<!-- http://localhost:8080/jspdemo/el03.jsp?city=bj&city=sh&city=cc -->
<c:forEach items="${paramValues.city}" var="city">
${city}
</c:forEach>
自定义标签
- 写一个java类,继承SimpleTagSupport类。
- override doTag方法。
- 在.tld文件中描述该标签。
示例:要写一个标签:输出指定内容的指定次数,如下
<!-- info:表示要输出的内容,qty:表示输出的次数(以下会打印10遍Hello World) -->
<t:hello info="Hello World<br>" qty="10" />
<!-- 输出指定格式的时间 -->
<t:date pattern="yyyy/MM/dd" />
-
写一个java类,继承SimpleTagSupport类。
package tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport; /** * 自定义标签类 * (要继承SimpleTagSupport) * (要从写doTag方法) * (标签有哪些属性,则标签类也要有对应的属性。属性名要相同,类型要匹配,并且要有对应的set方法) */ public class HelloTag extends SimpleTagSupport { private String info; private int qty; public HelloTag() { // 此构造方法可以不写(这里为了测试它的执行流程添加了此构造方法) System.out.println("HelloTag()构造器执行了"); } public void setInfo(String info) { System.out.println("info():"+info); this.info = info; } public void setQty(int qty) { System.out.println("qty():"+qty); this.qty = qty; } @Override public void doTag() throws JspException, IOException { /* * 通过继承自SimpleTagSupport类提供方法来获得PageContext * PageContext提供了用来获取其他隐含对象的方法 */ System.out.println("HelloTag.doTag()"); PageContext pctx = (PageContext)getJspContext(); JspWriter out = pctx.getOut(); for (int i = 0; i < qty; i++) { out.print(info); } } }
package tag; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport; /** * 自定义标签类 * (要继承SimpleTagSupport) * (要从写doTag方法) * (标签有哪些属性,则标签类也要有对应的属性。属性名要相同,类型要匹配,并且要有对应的set方法) */ public class DateTag extends SimpleTagSupport { private String pattern; public void setPattern(String pattern) { this.pattern = pattern; } @Override public void doTag() throws JspException, IOException { System.out.println("DateTag.doTag()"); PageContext pctx = (PageContext)getJspContext(); JspWriter out = pctx.getOut(); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat(pattern); String str = sdf.format(date); out.print(str); } }
-
在.tld文件中描述该标签。
创建mytag.tld文件
<?xml version="1.0" encoding="UTF-8" ?> <taglib 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-jsptaglibrary_2_1.xsd" version="2.1"> <!-- <description>JSTL 1.1 core library</description> 描述,可删除 <display-name>JSTL core</display-name> 描述,可删除 --> <tlib-version>1.1</tlib-version> <short-name>t</short-name> <uri>test</uri> <tag> <!-- 标签名 --> <name>hello</name> <!-- 标签类完整名字(tag包下的HelloTag类) --> <tag-class>tag.HelloTag</tag-class> <!-- body-content用来设置标签体的内容 其值主要有三个: empty:该标签没有标签体(如<t:hello info="Hello World" qty="100" />) scriptless:该标签有标签体,但是标签体的内容不能够出现Java代码 (即不能够出现<% %>,<%= %>,<%! %>) JSP:该标签有标签体,并且标签体的内容可以出现Java代码 (注:只有复杂标签技术才支持JSP,) --> <body-content>empty</body-content> <!-- 描述标签的属性 --> <attribute> <!-- 标签属性的描述 --> <description> info表示要输出的内容 </description> <!-- 标签的属性名 --> <name>info</name> <!-- 是否可选:true必须选择,不可缺省 --> <required>true</required> <!-- 是否可以动态赋值:true可以动态赋值(比如用el表达式进行计算) --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <description> qty表示输出的次数 </description> <name>qty</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <tag> <name>date</name> <tag-class>tag.DateTag</tag-class> <body-content>empty</body-content> <!-- 描述标签的属性 --> <attribute> <!-- 标签属性的描述 --> <description> pattern表示要输出时间的格式 </description> <!-- 标签的属性名 --> <name>pattern</name> <!-- 是否可选:true必须选择,不可缺省 --> <required>true</required> <!-- 是否可以动态赋值:true可以动态赋值(比如用el表达式进行计算) --> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
-
测试。创建hello.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!-- 标签所属的命名空间 --> <%@ taglib uri="test" prefix="t" %> <html> <head> <title></title> </head> <body style="font-size:30px"> <!-- 输出当前时间按pattern指定的格式 --> <t:date pattern="yyyy/MM/dd" /> <!-- info:表示要输出的内容,qty:表示输出的次数 --> <t:hello info="Hello World<br>" qty="10" /> </body> </html>
总结:
JSP 的执行原理?
当访问一个 JSP 页面时,该页面请求将会交给服务器中的 JSP 引擎去处理,它负责解释和执行 JSP 页面,每个 JSP 页面在第一次被访问时,JSP 引擎就会将它翻译成一个继承自 org.apache.jasper.runtime.HttpJspBase
类的 Servlet 源程序,接着再编译成 class 类文件,再由 Web 容器像调用普通 Servlet 程序一样的方式来装载和解释执行这个由 JSP 页面翻译成的 Servlet 程序。
request.getAttribute() 和 request.getParameter() 有何区别?
- request.getParameter() 通常用来接收接收表单的get或者post提交过来的参数;而request.getAttribute()一般和setAttribute()搭配使用,只有先set之后才能通过get方法获取到Object类型的数据
- getAttribute 返回的是对象,而getParameter 返回的是字符串
- getAttribute 和 setAttribute 只是在 web 容器内流转,仅仅是请求处理阶段;而 getParameter 取到的数据是通过容器来获取的。
JSP 与 Servlet 的区别?
- **JSP 实质上就是一个 Servlet。**可以理解为,JSP 是编译后的 “Servlet 类”;
- JSP 由 HTML 代码和 JSP 标签组成,更擅长页面显示;而 Servlet 更擅长流程控制;
- JSP 感觉像是 HTML 中嵌入 Java 代码,而 Servlet 有些像 Java 中嵌入 HTML 代码的意思。
JSP 有哪些内置对象(隐含对象)?作用分别是什么?
JSP 共有以下 9 个内置的对象:
- request:用户端请求,此请求会包含来自 GET/POST 请求的参数;
- response:表示一次响应对象;
- pageContext:表示当前的 JSP 对象;
- session:表示一次会话对象;
- application:表示当前应用对象;
- out:表示一个输出流对象;
- config:表示当前 JSP 的配置对象;
- page:表示当前页面;
- exception:表示异常对象。