六JSP技术
Posted shi_zi_183
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了六JSP技术相关的知识,希望对你有一定的参考价值。
JSP技术
JSP全名是Java Server Page,他是建立在Servlet规范上的动态网页开发技术。在JSP文件中,html代码与Java代码共同存在,其中,HTML代码用来显示静态内容的显示,Java代码用来实现网页中动态内容的显示。
与普通HTML有所区别,JSP文件的拓展名为.jsp。
在工程的WebRoot下创建一个JSP文件
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
当前时间是:
<%
out.print(new java.util.Date().toLocaleString());
%>
</body>
</html>
两次访问页面时间不同,说明此页面为动态页面。
JSP运行原理
当用户通过URL访问Servlet时,Web服务器会根据请求的URL地址在web.xml配置文件中查找匹配的<servlet-mapping>,然后将请求交给<servlet-mapping>指定的Servlet程序去处理。但是,上述例子中虽然没有在web.xml文件中找到与JSP相关的配置,但Web服务器仍然可以根据URL找到对应的JSP文件。这是因为在Tomcat服务器的web.xml文件中实现了JSP的相关配置。
这两个句配置,将所有.jsp .jspx的文件交给了JspServlet处理,Tomcat中的JSP引擎就是这个Servlet,该Servlet实现了对JSP页面的解析。
需要注意的是,JSP文件也可以像Servlet程序一样,在web.xml文件中进行注册和映射虚拟路径文件中进行注册和映射虚拟路径。注册JSP页面的方式与Servlet类似,只需将<servlet-class>元素修改为<jsp-file>元素即可。例如
<servlet>
<servlet-name>SimpleJspServlet</servlet-name>
<jsp-file>/simple.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>SimpleJspServlet</servlet-name>
<url-pattern>/myjsp</url-pattern>
</servlet-mapping>
其中<jsp-file>元素表示JSP文件,它表示的路径必须以/开始,这个/表示JSP所在的Web应用程序得到根目录
分析JSP所生成的Servletdaima
当用户第一次访问JSP页面时,该页面都会被JspServlet翻译成一个Servlet源文件,然后将源文件编译成.class文件。Servlet源文件和.class文件都放在”Tomcat安装目录/work/Catalina/localhost/应用名/“目录下。由JSP文件翻译成的Servlet类带有包名,包名为org.apache.jsp,因此simple.jsp生成的Servlet源文件和.class文件的目录为
可以看到simple.jsp文件被翻译成的class文件和Servlet源文件分别是simple_jsp.class和simple_jsp.java
打开simple_jps.java
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.109
* Generated at: 2021-07-16 02:29:48 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class simple_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
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;
out.write("\\r\\n");
out.write("<!DOCTYPE html PUBLIC \\"-//W3C//DTD HTML 4.01 Transitional//EN\\" \\"http://www.w3.org/TR/html4/loose.dtd\\">\\r\\n");
out.write("<html>\\r\\n");
out.write("<head>\\r\\n");
out.write("<meta http-equiv=\\"Content-Type\\" content=\\"text/html; 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褰撳墠鏃堕棿鏄細\\r\\n");
out.write("\\t");
out.print(new java.util.Date().toLocaleString());
out.write("\\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);
}
}
}
从上面的代码可以看出,simple.jsp文件翻译后的Servlet类名为simple_jsp,他没有实现Servlet接口,但继承了org.apache.jasper.runtime.HttpJspBase类。在Tomcat源文件中查看HttpJspBase类源代码,可以看到
HttpJspBase类是HttpServlet的一个子类,因此simple_jsp.java就是一个Servlet
JSP基本语法
JSP模板元素
JSP页面可以按照编写HTML页面的方式来编写,其中可以包含HTML文件的所有静态内容,在静态的HTML内容之中可以嵌套JSP的其他各种元素来产生动态内容的执行业务逻辑。JSP页面中的静态HTML内容成为JSP模板元素。JSP模板元素定义了网页的基本骨架,即定义了页面的结构和外观
JSP表达式
JSP表达式用于将程序数据输出到客户端,他将要输出的变量或者表达式直接封装在以"<%= %>"中
<%=expression%>
JSP脚本片段
JSP脚本片段是指嵌套在<% %>之中的一条或多条Java程序代码,这些Java代码必须严格遵守Java语法规范,否则编译会报错,例如
<h2>标题</h2>
<%
int x=3;
out.println(x);
%>
需要注意,在一个JSP页面中可以出现多个脚本片段,在两个或者多个脚本片段之间可以嵌套文本、HTML标记或JSP元素,并且这些脚本的代码可以互相访问。
demo.jsp
<%for(int i=1;i<3;i++){ %>
<h<%=i %>><%=i %>级标题</h<%=i %>>
<%} %>
被翻译成了demo_jsp.java
JSP声明
当JSP页面被翻译成Servlet程序时,JSP中包含的脚本片段、表达式、模板元素都将转化为Servlet中_jspService()方法的程序代码。这时,JSP脚本片段中定义的变量都将成为_jspServlet()方法,从而会出现程序的方法中再定义方法,这样的语法是错误的,为了解决这样的问题在JSP技术中提供了声明,它以"<%! %>"结束,其语法格式
<%! %>
上述语法格式中,被声明的java代码都将被翻译到Servlet的_jspServlet()方法之外,即在JSP声明中定义的都是成员方法、成员变量、静态方法、静态变量、静态代码块。
同脚本片段一样,在一个JSP页面中可以有多个JSP声明,单个声明中的Java语句可以是不完整的,但是多个声明组合后的结果必须是完整的。
demo.jsp
<%!static {
System.out.println("statice code block");
}%>
<%!
private int i=9;
public static java.lang.String str="www.baidu.cn";
public void jspInit(){
System.out.println("init method");
System.out.println("i="+i);
System.out.println("str="+str);
}
%>
demo_jsp.java
这里不仅静态代码块被执行了,jspInit()方法也被执行了,这是因为Tomcat在创建某个Servlet实例对象后,将调用init()方法进行初始化,而JSP页面所生成的Servelt的init()方法内部调用了jspInit()方法,所以当第一次访问demo.jsp页面时,都调用jspInit()方法进行JSP页面的初始化。
JSP注释
<%-- 注释信息 --%>
需要注意的是Tomcat在将JSP页面翻译成Servlet程序时,会忽略JSP页面中被注释的内容,不会将注释信息发送到客户端,但是在jsp中使用HTML注释仍可以发送到客户端。
JSP指令
JSP2.0中共定义了page、include、taglib三种指令,每种指令都定义了各自的属性。
page指令
<%@page 属性名="属性值"%>
属性名称 | 取值范围 | 描述 |
---|---|---|
language | java | 指明解释JSP文件时采用的语言,默认JAVA |
extends | 任何类的全名 | 编译该JSP时继承哪个类。JSP为Servlet,因此当指明继承不同类时需要实现Servlet的init()、destroy()方法 |
import | 任何包名、类名 | 指定在JSP页面翻译成的Servlet源文件中导入的包或类。import是唯一可以声明多次的page指令属性,一个属性可以引用多个类,中间用英文逗号隔开,JSP中默认引入java.lang.* java.servlet.* java.servlet.jsp.* java.servlet.http.* |
session | ture、false | 指明JSP中是否内置Session对象,默认ture |
autoFlush | ture、false | 指明是否运行缓存。如果为ture使用out.println()等方法输出的字符串并不会立即缓存到客户端,而是暂时存在缓冲区里,缓存满或者程序执行完毕,或执行out.flush()才会到客户端,默认ture |
buffer | none或者数组+kb | 指定缓存大小,当autoFlush设为ture时有效 |
isThreadSafe | ture、false | 指定线程是否安全。如果为ture则多个线程同时运行,否则只运行一个线程,默认为ture |
isErrorPage | ture、false | 指定该页面是否为错误处理页面,如果为ture,则该JSP内置一个Exception对象的exception,可直接使用。默认情况下,isErrorPage的值为false |
errorPage | 某个JSP页面的相对路径 | 指定一个错误页面,如果该JSP抛出一个未捕捉的异常,则跳转到errorPage |
contentType | 有效 的文档类型 | http协议中Content-Type的值 |
info | 任意字符 | 指明JSP的信息,该信息可以通过Servlet.getServletInfo()方法获取到 |
trimDirectiveWhitespace | ture、flase | 是否去掉指令前后的空白字符,默认为ture |
include指令
有时候,需要在JSP页面静态包含一个文件,例如HTML文件、文本文件等。
这是可以通过include指令
<%@include file="relativeURL"%>
file属性用于指定被引入文件的相对路径。
include.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
欢迎你,现在的时间是:
<%@ include file="date.jsp" %>
</body>
</html>
date.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
b{
color:#ff0000
}
</style>
</head>
<body>
<b><%out.println(new java.util.Date().toLocaleString()); %></b>
</body>
</html>
浏览器会忽略文件中重复的html标签、body标签、head标签、<!>声明
网站源码
浏览器容错之后的源码
JSP隐式对象
隐式对象
在JSP页面中,有一些对象需要频繁的使用,如果每次创建这些对象会非常麻烦。为此,JSP提供了9个隐式对象,他们是JSP默认创建的,可以直接在JSP页面使用。
隐式对象名称 | 类型 | 描述 |
---|---|---|
out | javax,servlet.jsp.JspWriter | 用于页面输出 |
request | javax.servlet.http.HttpServletRequest | 得到用户请求信息 |
response | javax.servlet.http.HttpServletResponse | 服务器向客户端的回应消息 |
config | javax.servlet.ServletConfig | 服务器配置,可以取得初始化参数 |
session | javax.servlet.http.HttpSession | 用来保存用户的信息 |
application | javax.servlet.ServletContext | 所有用户的共享信息 |
page | java.lang.Object | 指当前页面转换后的Servlet类的实例 |
pageContext | javax.servlet.jsp.PageContext | JSP的页面容器 |
exception | java.lang.Throwable | 表示JSP页面所发生的异常,在错误页面中才起作用 |
out对象
在JSP页面中,经常需要向客户端发送文本内容,这是,可以使用out对象来实现,out对象的类型是JspWriter,它相当于一种带缓存功能的PrintWriter。
在JSP页面中,通过对象写入数据相当于将数据插入到JspWriter对象的缓冲区中,只有调用了ServletResponse.getWriter()方法,缓冲区的数据才能真正写入到Servlet引擎所提供的缓冲区中。
out.jsp
<%="直接输出<br>" %>
<%
out.println("first line<br>");
response.getWriter().println("second line<br>");
%>
可以看到尽管out.println在request.getWriter().println之前但是它的输出内容却在后面。由此可以说明out对象通过print语句写入数据后,直到整个JSP页面结束,out对象中输入缓冲区的数据才真正写入Servlet引擎提供的缓冲区中,而request.getWriter().println则是直接把内容写入Servlet引擎的缓冲区。
因此request.getWriter().println会引起HTML内容错乱
可以看到request.getWriter().println提前与html结构输出,且如果out中的输出足够多,导致缓存满了输出到了Servlet引擎,此时request.getWriter().println可能会穿插在html文档中出现,导致结构混乱。
pageContext对象
在JSP页面中,想要获取JSP的隐式对象,可以使用pageContext对象。
获取隐式对象的方法
方法名 | 功能描述 |
---|---|
Jspwriter getOut() | 用于获取out隐式对象 |
Object getPage() | 用于获取page隐式对象 |
ServletRequest getRequest() | 用于获取request隐式对象 |
ServletResponse getResponse() | 用于获取response隐式对象 |
HttpSession getSession() | 用于获取session隐式对象 |
Exception getException() | 用于获取exception隐式对象 |
ServletConfig getServletConfig() | 用于获取config隐式对象 |
ServletContext getServletContext() | 用于获取application隐式对象 |
这样当传递一个pageContext对象后,就可以通过这些方法来轻松获取其他的8个隐式对象。
需要注意的是,虽然在JSP页面中可以直接使用隐式对象但是通过pageContext对象获取其他隐式对象的功能是必不可少的,在后面标签的学习中,需要将Java代码从JSP页面移除,这是JSP隐式对象也需要传递给java类中定义的方法。通常情况,只传递一个pageContext对象,然后通过它来调用其他的隐式对象。
pageContext对象不仅提供了获取隐式对象的方法,还提供了存储数据的功能。pageContext对象存储数据是通过操作属性来实现的
方法名称 | 功能描述 |
---|---|
void setAttribute(String name,Object value,int scope) | 用于设置pageContext的属性 |
Object getAttribute(String name,int scope) | 用于获取pageContext的属性 |
void removeAttribute(String name,int scope) | 删除指定范围内名称为name的属性 |
void removeAttribute(String name) | 删除所有范围内名称为name的属性 |
Object findAttribute(String name) | 从4个域对象中查找名称为name的属性 |
pageContext对象的作用范围有4个值
1、pageContext.PAGE_SCOPE:表示页面范围
2、pageContext.REQUEST_SCOPE:表示请求范围
3、pageContext.SESSION_SCOPE:表示会话范围
4、pageContext.APPLICATION_SCOPE:表示Web应用程序范围
需要注意的是:findAttribute会按上述顺序依次查找。
exception对象
需要注意的是,exception对象只有在错误处理页面才可以使用,即page指令中指定了属性<%@page isErrorPage=“true”%>的页面
price.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page errorPage="execp.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
String strprice = request.getParameter("price");
double price = Double.parseDouble(strprice);
out.println("Total price=" + price * 3);
%>
</body>
</html以上是关于六JSP技术的主要内容,如果未能解决你的问题,请参考以下文章
谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js