JSP

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代码

    1. 方式一:java代码片段

      <% java代码 %>

      time:<%
          Date date = new Date();
          out.print(date);
      %>
      
    2. 方式二:jsp表达式

      <%= java表达式 %>

      time:<%= new Date() %>
      
    3. 方式三:jsp声明

      <%! 声明变量或者方法 %>

      <%!
          String info = "您好";
      %>
      <%= info>
      <%!
          int sum(int a,int b){
          	return a + b;
      	}
      %>
      <%= sum(2,4) %>
      
      // 这个编译成.java文件就是一个成员变量或者方法,它不在service方法中!!!
      
  • 隐含对象(内置对象)

    1. 什么是隐含对象?

      直接可以使用的对象,比如out、request和response。
      
      out = pageContext.getOut();
      
    2. 为什么可以直接使用这些隐含对象?

      容器会自动添加获得这些对象的代码。
      
    3. 有哪些隐含对象?

      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>
 ```
  • 指令

    1. 什么是指令?

      通知容器,在将JSP转换成对应的Servlet时做一些额外的处理,比如导包。

    2. 语法格式

      <%@ 指令名  属性=值  %>
      
    3. 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)
      在这里插入图片描述

  1. 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>
  1. 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组件继续做。

    1. web组件是Servlet和JSP的统称
    2. 常用的场景是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’]}

  1. [ ]里面可以出现绑订名。
  2. [ ]里面可以出现从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>
  • 做一些简单的运算。
  1. 算术运算

    + 、-、*、/、%
    注: " + " 只能求和。
    
  2. .关系运算

    >>=<<===!=
    
  3. 逻辑运算

    &&||、!
    
  4. 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>
    
  • 读取请求参数值
  1. ${param.username}等价于
    ​ String username = request.getParameter(“username”);

  2. ${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>&nbsp;
        </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" />
  1. 写一个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);
    	}
    }
    
  2. 在.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>
    
  3. 测试。创建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() 有何区别?

  1. request.getParameter() 通常用来接收接收表单的get或者post提交过来的参数;而request.getAttribute()一般和setAttribute()搭配使用,只有先set之后才能通过get方法获取到Object类型的数据
  2. getAttribute 返回的是对象,而getParameter 返回的是字符串
  3. getAttribute 和 setAttribute 只是在 web 容器内流转,仅仅是请求处理阶段;而 getParameter 取到的数据是通过容器来获取的。

JSP 与 Servlet 的区别?

  1. **JSP 实质上就是一个 Servlet。**可以理解为,JSP 是编译后的 “Servlet 类”;
  2. JSP 由 HTML 代码和 JSP 标签组成,更擅长页面显示;而 Servlet 更擅长流程控制;
  3. JSP 感觉像是 HTML 中嵌入 Java 代码,而 Servlet 有些像 Java 中嵌入 HTML 代码的意思。

JSP 有哪些内置对象(隐含对象)?作用分别是什么?

JSP 共有以下 9 个内置的对象:

  1. request:用户端请求,此请求会包含来自 GET/POST 请求的参数;
  2. response:表示一次响应对象;
  3. pageContext:表示当前的 JSP 对象;
  4. session:表示一次会话对象;
  5. application:表示当前应用对象;
  6. out:表示一个输出流对象;
  7. config:表示当前 JSP 的配置对象;
  8. page:表示当前页面;
  9. exception:表示异常对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值