使用Servlet实现动态网页,需要调用大量的输出语句,导致程序非常臃肿;JSP可以解决这个问题,JSP全名为Java Server Page,它是建立在Servlet规范之上的动态网页开发技术。在JSP文件中,HTML代码与Java代码共同存在,HTML代码用来实现网页中静态内容的显示,java代码用来实现网页中动态内容的显示,JSP文件的扩展名为.jsp。
一 JSP原理
1.JSP相关配置
在<Tomcat安装目录>/conf/web.xml中有如下配置
<servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping>
可以看出,以.jsp为扩展名的URL访问请求是由JspServlet处理的,Tomcat中的JSP引擎就是这个Servlet程序,该Servlet程序实现了对所有JSP页面的解析。
2.JSP解析的代码
当用户第一次访问JSP页面时,该页面被JspServlet翻译成Servlet源码文件,然后将源文件编译成.class文件。例如index.jsp文件被请求后,生成index_jsp.java和index_jsp.class,并放在<Tomcat>安装目录/work/Catalina/localhost/应用名称下。
index.jsp
<%-- Created by IntelliJ IDEA. User: xi Date: 2017/5/29 Time: 11:12 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=utf-8" language="java" %> <html> <head> <title>请求和响应</title> </head> <body> <form action="/HelloServlet" method="GET"> 用户名:<input type="text" name="username"> 密 码:<input type="password" name="password"> <input type="submit" value="提交"> </form> </body> </html>
index_jsp.java
/* * Generated by the Jasper component of Apache Tomcat * Version: Apache Tomcat/9.0.0.M21 * Generated at: 2017-06-01 10:58:14 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 index_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent, org.apache.jasper.runtime.JspSourceImports { 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 static final java.util.Set<java.lang.String> _jspx_imports_packages; private static final java.util.Set<java.lang.String> _jspx_imports_classes; static { _jspx_imports_packages = new java.util.HashSet<>(); _jspx_imports_packages.add("javax.servlet"); _jspx_imports_packages.add("javax.servlet.http"); _jspx_imports_packages.add("javax.servlet.jsp"); _jspx_imports_classes = null; } 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 java.util.Set<java.lang.String> getPackageImports() { return _jspx_imports_packages; } public java.util.Set<java.lang.String> getClassImports() { return _jspx_imports_classes; } 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 java.lang.String _jspx_method = request.getMethod(); if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD"); return; } 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("\n"); out.write("\n"); out.write("<html>\n"); out.write(" <head>\n"); out.write(" <title>请求和响应</title>\n"); out.write(" </head>\n"); out.write(" <body>\n"); out.write(" <form action=\"/HelloServlet\" method=\"GET\">\n"); out.write(" 用户名:<input type=\"text\" name=\"username\">\n"); out.write(" 密 码:<input type=\"password\" name=\"password\">\n"); out.write(" <input type=\"submit\" value=\"提交\">\n"); out.write(" </form>\n"); out.write(" </body>\n"); out.write("</html>\n"); } 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和html
jsp页面中可以包含html所有标记元素来产生静态元素,html中可以嵌套jsp的各种元素来产生动态内容和业务逻辑。
2.jsp表达式
语法:<%=expression%>
expression:变量或表达式。
jsp表达式用于将变量或表达式的计算结果转换成字符串,输出到客户端。
例如:
<%=new Date().toLocaleString()%>
3.jsp脚本
语法:<%java代码%>
在一个jsp页面中,可以出现多个脚本片段,在脚本片段之间可以有其他文本,html标记或其他jsp元素。在同一个jsp页面中,所有的脚本片段组成一个完整的java代码逻辑,无论有多少个脚本片段,它们都是一个逻辑整体,不同脚本间是可以相互访问的。
4.jsp声明
当jsp页面被翻译成Servlet程序时,jsp中包含的脚本片段,表达式,模板元素都将转换为Servlet中_jspService()方法的程序代码。这时,jsp脚本片段中定义的变量豆浆成为_jspService()方法中的局部变量,而jsp脚本片段中定义的方法也被插入到_jspService方法中,这样就出现了方法中定义方法,出现了错误。jsp声明可以解决上述问题。
语法:
<%!
java声明
%>
说明:在声明中定义成员变量,成员方法,静态方法,静态变量,静态代码块,这些内容会被转换为_jspService()方法之外的代码。同jsp脚本一样,在jsp页面中可以有多个jsp声明,单个声明中的java语句可以是不完整的。
5.jsp注释
语法:<%--注释--%>
jsp页面中也有html内容,因此也可以使用html注释,但html注释内容会被原文输出给客户端。
三 jsp指令
1.page指令
语法:<%@page 属性名="属性值"%>
属性名称 | 取值范围 | 描述 |
language | java | 解释该JSP文件采用的语言,默认java |
extends | 任何类的全名 | 指明编译该jsp文件时继承哪个类 |
import | 任何包名或类名 | 指定在jsp页面翻译成Servlet源文件中导入的包或类 |
session | true,false | 指明jsp内是否内置Session对象 |
autoFlush | true,false | 指明是否运行缓存,如果为true,使用out.println()等方法输出的字符串并不立即缓存到客户端服务器,而是暂存到缓冲区,只有当缓存区满或程序执行完毕或执行out.flush()操作才会输出到客户端,默认为true |
buffer | none或者数字kb | 指定缓存区的大小 |
isThreadSafe | true或false | 指定jsp是否线程安全 |
isErrorPage | true或false | 指定该页面是否为错误处理页面,为true,则该jsp内置有一个Exception对象的exception |
errorPage | jsp页面的相对路径 | 指定一个错误界面,如果该jsp抛出一个未捕获的异常,则跳转到errorPage指定页面,errorPage指定页面需指定isErrorPage为true |
contentType | 文档类型 | 浏览器根据该属性判断文档类型: HTML为text/html 纯文本为text/plain JPG为image/jpeg GIF为image/gif Word为application/msword |
info | 任意字符串 | 指明jsp的附加信息 |
trimDirectiveWhitespace | true,false | 是否去掉指令前后的空白字符 |
2.include指令
在jsp页面静态包含一个文件。
语法:<%@include file="relativeURL"%>
注意:包含文件插入位置为include指令在jsp中的位置;"/"路径开头表示对于当前Web应用程序根目录,否则相对于当前文件。
四 jsp隐式对象
jsp提供了9个隐式对象,它们是JSP默认创建的,可以直接在jsp页面使用。
对象名称 | 类型 | 描述 |
out | JspWriter | 用于页面输出,带缓存功能 |
request | HttpServletRequest | 客户端请求信息 |
response | HttpServletResponse | 服务器回应信息 |
config | ServletConfig | 服务器配置 |
session | HttpSession | 保存用户信息 |
application | ServletContext | 所有用户的共享信息 |
page | Object | 当前页面转换后的Servlet类的实例 |
pageContext | PageContext | jsp页面容器 |
exception | Throwable | jsp中的异常,在错误页面中起作用 |
1.pageContext
它代表当前jsp的运行环境,主要有两个作用:
- 获取其他8个隐式对象。
- 通过操作属性实现数据存储。
pageContext对象有4个作用范围:
- PAGE_SCOPE:页面范围
- REQUEST_SCOPE:请求范围
- SESSION_SCOPE:会话范围
- APPLICATION_SCOPE:web应用程序范围
五 jsp标签
1.<jsp:include>标签
同RequestDispatcher的include()方法。
2.<jsp:forward>标签
同RequestDispatcher的forward()方法。