JSP基础知识

JSP是简化Servlet编写的一种技术,它将Java代码和HTML语句混合在同一个文件中编写,只对网页中要动态产生的内容采用Java代码来编写。而对固定不变的静态内容采用普通静态HTML页面方式编写。

目录

一、JSP运行原理

二、JSP中的隐含对象

1.九个隐含对象

2.域对象

三、JSP基本语法

1.注释

2.JSP脚本片段

3.JSP表达式

4.JSP声明

5.JSP指令

page指令

include指令:静态包含

动态包含

静态包含和动态包含的区别于联系

四、JSP中错误页面的处理

1.局部处理

2.全局处理


 

一、JSP运行原理

JSP本质上是一个Servlet,即与Servlet中相关的方法都可以在JSP中调用。工作原理如下图:

如下为一个jsp文件转换为.java文件后的程序。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>JSP</h1>
	<p>你好。。。。。。。。。。</p>
	<form action="b.jsp" method="post">
		姓名:<input type="text" name="name" />
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

转换后的Java文件路径,以eclipse为例:工程\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\JspProject\org\apache\jsp  转化结果部分如下

public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

    public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {    
    //省略一部分代码
        //这些是JSP的内置对象
        final javax.servlet.jsp.PageContext pageContext;
        javax.servlet.http.HttpSession session = null;
        final javax.servlet.ServletContext application;
        final javax.servlet.ServletConfig config;
        javax.servlet.jsp.JspWriter out = null;
        final java.lang.Object page = this;
        javax.servlet.jsp.JspWriter _jspx_out = null;
        javax.servlet.jsp.PageContext _jspx_page_context = null;
        
        try {
          response.setContentType("text/html; charset=UTF-8");
          pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);
          _jspx_page_context = pageContext;
          application = pageContext.getServletContext();
          config = pageContext.getServletConfig();
          session = pageContext.getSession();
          out = pageContext.getOut();
          _jspx_out = out;

          //JSP中的HTML代码利用IO的方式发送给客户端,所以客户端可以加载出HTML页面
          out.write("\r\n");
          out.write("<!DOCTYPE html>\r\n");
          out.write("<html>\r\n");
          out.write("<head>\r\n");
          out.write("<meta charset=\"UTF-8\">\r\n");
          out.write("<title>Insert title here</title>\r\n");
          out.write("</head>\r\n");
          out.write("<body>\r\n");
          out.write("\t<h1>JSP</h1>\r\n");
          out.write("\t<p>你好。。。。。。。。。。</p>\r\n");
          out.write("\t<form action=\"b.jsp\" method=\"post\">\r\n");
          out.write("\t\t姓名:<input type=\"text\" name=\"name\" />\r\n");
          out.write("\t\t<input type=\"submit\" value=\"提交\"/>\r\n");
          out.write("\t</form>\r\n");
          out.write("</body>\r\n");
          out.write("</html>");
        } catch (java.lang.Throwable t) {
          if (!(t instanceof javax.servlet.jsp.SkipPageException)){
            out = _jspx_out;
            if (out != null && out.getBufferSize() != 0)
              try {
                if (response.isCommitted()) {
                  out.flush();
                } else {
                  out.clearBuffer();
                }
              } catch (java.io.IOException e) {}
            if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
            else throw new ServletException(t);
          }
        } finally {
            _jspxFactory.releasePageContext(_jspx_page_context);
        }
      }
    }
}

二、JSP中的隐含对象

1.九个隐含对象

从上面JSP文件转换后的.java文件我们可以很轻易的得知,其中HTML代码是用IO的方式发送给客户端的,不仅如此我们还可以发现该方法中暴露出来的几个对象,对应到JSP文件中也叫JSP的隐含对象,其实隐含对象一共有九个,如下:

requestHttpServletRequest的对象实例
responseHttpServletResponse的对象实例
pageContext表示页面的上下文,它是javax.servlet.jsp.PageContext的对象实例,可以通过该对象获取其他8个隐含对象,也可以通过它来获取到当前页面的其他信息。
sessionHttpSession的对象实例
application当前Web应用的全局变量,是ServletContext的对象实例
configServletConfig的对象实例
outJspWriter的对象实例。
page表示当前JSP转换后的Servlet对象,但其被声明为Object类型
exception在声明了page指令的isErrorPage=“true”才可以使用,由于上面并没有声明,所以找不到该对象。

注意:通过查看JSP对应的Servlet文件我们可以知道这些隐含对象虽然可以在JSP文件中直接使用,但是这些变量却是Servlet中的_jspService方法的局部变量,所以JSP中的内容都隶属于该方法。 

2.域对象

其中pageContext,request,session,application又被称为四大域对象。原因是它们四个都可以存储和获取指定的属性,只是作用范围不同。下面作用范围从小到大排列为:

  1. pageContext:属性的作用范围仅为当前JSP页面。
  2. request:属性的作用范围仅限于同一请求。
  3. session:属性的作用范围仅限于一次会话。
  4. application:属性的作用范围限于当前web应用,是最大的属性作用范围,只要在一处设置属性,在本项目的其他各处的JSP或Servlet中都可以获取到。

测试同一请求下四大域对象中属性值的变化,如下(浏览器访问attr1.jsp页面,attr1将请求转发至attr2.jsp):

attr1.jsp如下

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>attr1页面</h1>
	<%
		pageContext.setAttribute("pageContext", "attr1中设置的pageContext属性值");
		request.setAttribute("request", "attr1中设置的request属性值");
		session.setAttribute("session", "attr1中设置的session属性值");
		application.setAttribute("application", "attr1中设置的application属性值");
		//此处进行请求的转发
		request.getRequestDispatcher("./attr2.jsp").forward(request, response);
	%>
</body>
</html>

attr2.jsp如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>attr2页面</h1>
	<p>
		pageContext:<%=pageContext.getAttribute("pageContext") %>
	</p>
	<p>
		request:<%=request.getAttribute("request") %>
	</p>	
	<p>
		session:<%=session.getAttribute("session") %>
	</p>	
	<p>
		application:<%=application.getAttribute("application") %>
	</p>
</body>
</html>

结果如下:

三、JSP基本语法

1.注释

<%-- JSP注释信息写在这里 --%>
<!-- HTML注释信息写在这里 -->
<%
    //Java代码注释写在这里
    /*
        或者
        写在这里
    */
%>

JSP注释是对浏览器隐藏的,浏览器控制台无法查看JSP注释,但是可以查看HTML注释。

2.JSP脚本片段

JSP脚本片段是指嵌套在<% 和 %> 之中的一条或多条Java代码。多个脚本片段中的代码可以相互访问。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP脚本片段测试</title>
</head>
<body>
	<% 
		final int count = 10;  
		for(int index = 0; index < count; index++){
	%>
			<p>我是第<%=(index + 1) %>行,总共有<%=count %>行</p>		
	<%
		}
	%>
</body>
</html>

3.JSP表达式

JSP表达式用于向页面中输出信息,其语法格式如下:

<%= 表达式%> 

注意:表达式的最终运算结果将被转换为字符串显示到浏览器页面上。

示例:

<%
    Date date = new Date();
%>
<%-- 注意下面两条语句是等价的 --%>
<% out.print(date); %>
<%= date%>

4.JSP声明

JSP声明用于声明变量和方法。JSP声明的语法格式如下:

<%! 此处声明变量和方法 %>

由于JSP文件本质上是Servlet,其需要转换为.java文件,在服务器端执行,所以对于变量的声明注意区别如下代码:

<% String str1 = "123"; %>
<%! String str2 = "123" %>

这两者是不一样的,因为str1变量最终转换为Servlet后其实质是_jspService方法的局部变量,而str2变量却是转换后Servlet类的成员变量,所以str1不可以是static修饰的,而str2可以。当然还可以声明方法,如下:

<%-- 声明JSP文件转化为Servlet之后的对象方法 --%>
<%!
    public int method(int count){
	return count + 10;
    }
%>

5.JSP指令

JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。语法格式如下:

<%@ 指令 属性名 = "属性值" %>

在JSP2.0中,定义了page、include和taglib这三种指令,每种指令中又都定义了一些各自的属性,如果需要在一个JSP页面中设置同一条指令的多个属性,可以使用多条指令单独设置每个属性,也可以使用同一条指令设置该指令的多个属性。

<%@ page ... %>定义网页依赖属性,比如脚本语言、error页面、缓存需求等等
<%@ include ... %>包含其他文件
<%@ taglib ... %>引入标签库的定义

page指令

page指令相关的属性如下:

include指令:静态包含

JSP可以通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是该JSP文件的一部分,会被同时编译执行。Include指令的语法格式如下:

<%@ include file="文件相对 url 地址" %>

注意利用上述方式包含的文件被称为静态包含或静态引入。静态包含最终只会转化为同一个Servlet,它是先包含后编译。它就像是将被包含的JSP文件中的代码复制粘贴到目标文件中一样。类似于C语言中include指令引入文件。

test2.jsp如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>test2</title>
</head>
<body>
	<%! 
		static final int DEFAULT_NUMBER = 1; 
		public void test2Method(){
			//TODO
		}
	%>
	<% 
		String str = "test2";
	%>
</body>
</html>

test1.jsp中静态包含test2.jsp如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>test1</title>
</head>
<body>
	<%--这里包含test2.jsp文件,该文件中定义的变量方法都会出现在同一个Servlet中 --%>
	<%@ include file="test2.jsp" %>
	<%
		/*
			注意这里由于上面已经静态包含了test2.jsp,在test2.jsp中已经定义了str变量。
			由于静态包含只会转化为同一个Servlet,先包含后编译。所以下面不能定义str变量,会编译不通过。
		*/
		//String str = "123";
		//注意此处的str2和test2.jsp中的str两个变量均被定义在同一个Servlet类的_jspService方法中
		String str2 = "test1";
	%>
</body>
</html>

动态包含

使用动态包含的语法格式如下:

<jsp:include page="test2.jsp">
    <%--这里为子标记可以传递参数,然后在test2.jsp中可以通过request.getParameter()获取值--%>
    <jsp:param value="XXX" name="XXX"/>
</jsp:include>

区别于静态包含,动态包含会产生两个Servlet文件,因为在两个类中所以变量名可以重复。动态包含会产生两个Servlet文件,主文件和被包含的文件各自对应一个Servlet,在运行主文件时才将被包含JSP文件的运行结果引入进来

test2.jsp如下:

<body>
	<% 
		String str = "test2";
	%>
	<p>我是test2中的内容</p>
	<%=str %>
</body>

test1.jsp动态包含test2.jsp如下:

<body>
	<jsp:include page="test2.jsp"></jsp:include>
	<%
		String str = "test1";
	%>
</body>

那么test1.jsp对应的Servlet中只会引入如下第一行代码,include方法转向test2.jsp页面:

//省略……
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "test2.jsp", out, false);
out.write('\r');
out.write('\n');
out.write('	');

String str = "test1";
	
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>");
//省略……

访问test1.jsp,浏览器显示如下:

静态包含和动态包含的区别于联系

  1. 处理时间和方式不同:静态包含的文件在页面转译时就合并到一起了,被包含文件与当前页面组合而成的新页面必须符合JSP的语法和逻辑规则,由于是提前合并编译,所以执行速度快;而动态包含是被包含文件语法和逻辑独立于当前页面,单独被JSP引擎编译,当前页面执行时再将被包含文件的运行结果传送给客户端,由于是执行页面时处理包含文件,所以执行速度慢,但是可以通过param子标记传递参数,比较灵活。
  2. 适用情况不同:静态导入适合导入不会经常变化的资源例如HTML文件,而动态导入适合一个时常变化的资源例如JSP文件。 
  3. 相同点:二者最终只产生一个HTML页面。

四、JSP中错误页面的处理

在web项目中我们经常会遇到需要显示自定义的错误页面的情形,以下有两种方式。

1.局部处理

在可能发生错误的JSP页面声明page指令的errorPage=“需要转向的错误页面地址”。(error.jsp)

在错误页面error.jsp中如果设置isErrorPage = “true”,就可以使用exception对象打印出错误信息。

2.全局处理

在web.xml中配置。

指定错误代号的方式

<error-page>
  	<!-- 指定错误代号 -->
  	<error-code>404</error-code>
  	<!-- 指定出错了要去的页面地址 -->
    <location>/error.jsp</location>
</error-page>

指定错误类型的方式

<error-page>
  	<!-- 这里可以指定错误类型 -->
  	<exception-type>java.lang.Exception</exception-type>
  	<location>/error.jsp</location>
</error-page>

需要注意的是:如果局部和全局一起配置的话会优先跳转到errorPage指定的页面,如果要使用全局配置必须先删除errorPage。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值