Java Web学习总结(7)JSP(一)
一,JSP基础语法
1,JSP模板元素
JSP页面中的HTML内容称之为JSP模版元素。
JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。
2,JSP脚本片段
JSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码(在<%%>不能定义方法)。语法:<%多行java代码 %>
例如:
<%
int num = 0;
num = ++num;
out.println("num:" + num);
%>
注意:
1,JSP脚本片断中只能出现java代码,不能出现其它模板元素, JSP引擎在翻译JSP页面中,会将JSP脚本片断中的Java代码将被原封不动地放到Servlet的_jspService方法中。
2,JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每执行语句后面必须用分号(;)结束。
3,在一个JSP页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。
4,多个脚本片断中的代码可以相互访问
3,JSP表达式
JSP脚本表达式(expression)用于将程序数据输出到客户端,语法:<%=变量或表达式 %>
例如:
<%="123" %>
4,JSP声明
JSP页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。语法:<%!java代码 %>
JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法。
例如:
<%!
static {
System.out.println("静态代码块");
}
private String name = "Zender";
public void TestFun(){
System.out.println("成员方法!");
}
%>
<%
TestFun();
out.println("name:" + name);
%>
控制台:
页面:
5,JSP注释
在JSP中,注释有显式注释, 隐式注释,JSP自己的注释:
显式注释 |
直接使用HTML风格的注释:<!- - 注释内容- -> |
隐式注释 |
直接使用JAVA的注释://、/*……*/ |
JSP自己的注释 |
<%- - 注释内容- -%> |
区别:
HTML的注释在浏览器中查看源文件的时候是可以看得到的,而JAVA注释和JSP注释在浏览器中查看源文件时是看不到注释的内容的。
二,JSP原理
1,Web服务器是如何调用并执行一个jsp页面的?
浏览器向服务器发请求,不管访问的是什么资源,其实都是在访问Servlet,所以当访问一个jsp页面时,其实也是在访问一个Servlet,服务器在执行jsp的时候,首先把jsp翻译成一个Servlet,所以我们访问jsp时,其实不是在访问jsp,而是在访问jsp翻译过后的那个Servlet。
例如下面的代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%!
static {
System.out.println("静态代码块");
}
private String name = "Zender";
public void TestFun(){
System.out.println("成员方法!");
}
%>
<%
TestFun();
out.println("name:" + name);
%>
</body>
</html>
当我们通过浏览器访问index.jsp时,服务器首先将index.jsp翻译成一个index_jsp.class,在Tomcat服务器的work\Catalina\localhost\项目名\org\apache\jsp目录下可以看到index_jsp.class的源代码文件index_jsp.java
index_jsp.java的代码如下:
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 {
static {
System.out.println("静态代码块");
}
private String name = "Zender";
public void TestFun(){
System.out.println("成员方法!");
} 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");
out.write('\r');
out.write('\n');
out.write(' ');
TestFun();
out.println("name:" + name); 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);
}
}
}
源码
index_jsp这个类是继承org.apache.jasper.runtime.HttpJspBase这个类的,通过查看HttpJspBase源代码,可以知道HttpJspBase类是继承HttpServlet的,所以HttpJspBase类是一个Servlet,而index_jsp又是继承HttpJspBase类的,所以index_jsp类也是一个Servlet,所以当浏览器访问服务器上的index.jsp页面时,其实就是在访问index_jsp这个Servlet,index_jsp这个Servlet使用_jspService这个方法处理请求。
HttpJspBase源码如下:
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import javax.servlet.jsp.JspFactory;
import org.apache.jasper.compiler.Localizer;
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage{ protected HttpJspBase() {
}
public final void init(ServletConfig config)
throws ServletException
{
super.init(config);
jspInit();
_jspInit();
} public String getServletInfo() {
return Localizer.getMessage("jsp.engine.info");
}
public final void destroy() {
jspDestroy();
_jspDestroy();
}
/**
* Entry point into service.
*/
public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
_jspService(request, response);
} public void jspInit() {
}
public void _jspInit() {
}
public void jspDestroy() {
}
protected void _jspDestroy() {
}
public abstract void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException;
}
2,_jspService方法
问题1:Jsp页面中的html排版标签是如何被发送到客户端的?
浏览器接收到的这些数据,都是在_jspService方法中使用如下的代码输出给浏览器的。
问题2:Jsp页面中的java代码服务器是如何执行的?
在jsp中编写的java代码会被翻译到_jspService方法中去,当执行_jspService方法处理请求时,就会执行在jsp编写的java代码了,所以Jsp页面中的java代码服务器是通过调用_jspService方法处理请求时执行的。
3,jsp在服务器的执行流程
第一次执行:
- 客户端通过电脑连接服务器,因为是请求是动态的,所以所有的请求交给WEB容器来处理
- 在容器中找到需要执行的*.jsp文件
- 之后*.jsp文件通过转换变为*.java文件
- *.java文件经过编译后,形成*.class文件
- 最终服务器要执行形成的*.class文件
第二次执行:
- 因为已经存在了*.class文件,所以不在需要转换和编译的过程
修改后执行:
- 源文件已经被修改过了,所以需要重新转换,重新编译。
三,JSP指令
JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
1,Page指令
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
page指令的完整语法:
<%@ page
[ language="java" ]
[ extends="package.class" ]
[ import="{package.class | package.*}, ..." ]
[ session="true | false" ]
[ buffer="none | 8kb | sizekb" ]
[ autoFlush="true | false" ]
[ isThreadSafe="true | false" ]
[ info="text" ]
[ errorPage="relative_url" ]
[ isErrorPage="true | false" ]
[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ]
[ pageEncoding="characterSet | ISO-8859-1" ]
[ isELIgnored="true | false" ]
%>
import属性
可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号(,)分隔
<%@ page import="java.util.*,java.io.*,java.sql.*"%>
备注:
在Jsp页面中,Jsp引擎会自动导入下面的包
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
errorPage属性
使用errorPage属性指明出错后跳转的错误页面,errorPage属性的设置值必须使用相对路径,如果以"/"开头,表示相对于当前Web应用程序的根目录,否则,表示相对于当前页面。
比如index.jsp页面有如下的代码:
<%@ page language="java" errorPage="/error.jsp" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
//错误代码
int x = 1/0;
%>
</body>
</html>
在index.jsp中,page指令的errorPage属性指明了出错后跳转到"/error.jsp",error.jsp页面代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>error jsp</title>
</head>
<body>
<h1>对不起,出错了,请联系网站管理员解决!</h1>
</body>
</html>
运行结果如下:
我们也可以在在web.xml中使用<error-page>标签为整个web应用设置错误处理页面,web.xml的代码下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>JSP</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 404错误的处理页面 -->
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
</web-app>
error.jsp页面代码同上
当访问一个不存在的web资源时,就会跳转到在web.xml中配置的404错误处理页面error.jsp,如下图所示:
一个jsp页面是作为系统的错误处理页面,那么建议将page指令的isErrorPage属性(默认为false)设置为"true"来显式声明这个Jsp页面是一个错误处理页面。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%>
将error.jsp页面显式声明为错误处理页面后,Jsp引擎在将jsp页面翻译成Servlet的时候,在Servlet的 _jspService方法中会声明一个exception对象,然后将运行jsp出错的异常信息存储到exception对象中,由于Servlet的_jspService方法中声明了exception对象,那么就可以在error.jsp页面中使用exception对象。源码如下:
2,include指令
在JSP中对于包含有两种语句形式:
- @include指令
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。
语法:<%@ include file="relativeURL"%>
file属性用于指定被引入文件的路径。路径以"/"开头,表示代表当前web应用。
注意细节:
- 被引入的文件必须遵循JSP语法。
- 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments(片段))作为静态引入文件的扩展名。
- 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
- <jsp:include>标签
<jsp:include>标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法: <jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
page属性:用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性:指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
- <jsp:include>标签与include指令的区别
<jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。 而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
Java Web学习总结(7)JSP(一)的更多相关文章
- Java Web学习笔记之---JSP
Java Web学习笔记之---JSP (一)JSP常用语法 (1)HTML注释 <!--所要注释的内容 --> 在客户端显示一个注释. (2)隐藏注释 <%--所要注释的内容--% ...
- java web学习之初识jsp
用java语言(+html语言)开发动态资源的技术: jsp的运行过程,1:tomcat服务器将jsp代码翻译成java代码,并且编译成class文件 2:tomcat服务器构造类对象 3:tomca ...
- java web学习笔记-jsp篇
1.java web简介 1.1静态页面与动态页面 表现形式 所需技术 静态网页 网页内容固定,不会更新 html,css 动态网页 网页内容由程序动态显示,自动更新 html,css,DB,ja ...
- Java Web 学习路线
实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...
- Java web 学习之旅
java web学习之旅 来公司十天了,感觉已经慢慢地融入了这个环境中,几个学长人都很好,都是在他们帮助下,我才能比较顺利的开始了学习java web的旅途. 来这里学习的第一个阶段是做一个简单的用户 ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- java web 学习笔记 编码问题总结
java web 学习笔记 编码问题总结 1.非form表单中提交的中文参数---------------------------传递给Servlet服务器时,默认以iso-8859-1解码 ...
- Java Web 学习笔记 1
Java Web 学习笔记 1 一.Web开发基础 1-1 Java Web 应用开发概述 1.1.1 C/S C/S(Client/Server)服务器通常采用高性能的PC机或工作站,并采用大型数据 ...
- Java Web学习笔记之---EL和JSTL
Java Web学习笔记之---EL和JSTL (一)EL (1)EL作用 Expression Language(表达式语言),目的是代替JSP页面中复杂的代码 (2)EL表达式 ${变量名} ( ...
- JAVA Web学习笔记
JAVA Web学习笔记 1.JSP (java服务器页面) 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . JSP全名为Java Server Pages,中文名叫java服务器 ...
随机推荐
- fiddler抓取火狐浏览器上https协议请求
前言:现在很多网站采用https协议,当打开fiddler时.浏览https协议的网站会提示不安全,若使用fiddler抓取https协议的请求,则需要向浏览器导入证书,才能抓取https协议的请求, ...
- 【ABAP系列】SAP ABAP基础-程序优化及响应速度之LOOP
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-程序优化及 ...
- simhash文本相似度比较
simhash 在simhash中处理一个文本的步骤如下: 第一步,分词: 对文本进行分词操作,同时需要我们同时返回当前词组在文本内容中的权重(这基本上是目前所有分词工具都支持的功能). 第二步,计算 ...
- redis数据的备份与恢复
redis数据的备份与恢复 持久化分为两种方式:RDB和AOF 1.1 RDB模式 RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的所有数据进 ...
- JavaScript如何获得两点之间顺时针旋转的角度
接上回:如何用javascript中的canvas让图片自己旋转 既然能够制定角度让图片旋转,那么现在要做的是自动获得旋转的角度, 让图片能够随着鼠标的方向旋转,让人物能够面朝鼠标的方向: 源代码: ...
- Jenkins windows 执行批量cmd命令XCOPY 提示'XCOPY' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
由于Jenkins没有配置环境变量造成 打开Jenkins=>Manage Jenkins =>Configure System =>全局属性 新增全局变量 健: Path 值: % ...
- elasticsearch 基础 —— URI搜索
URI搜索 可以通过提供请求参数使用URI来执行搜索请求.使用此模式执行搜索时,并非所有搜索选项都会暴露.这是一个例子: GET twitter/_search?q=user:kimchy 示例响应: ...
- Android 虚线实现绘制 - DashPathEffect
前言: 通过view绘制虚实线,采用Android自带API--DashPathEffect.具体使用请参考更多的链接,这里只是讲解. 构造函数 DashPathEffect 的构造函数有两个参数: ...
- rsync之expect脚本shell
r_expect.sh: #!/bin/expect -f set timeout 30 #spawn rsync -avz --delete --exclude-from=exclude.list ...
- Tutorial1
一 Introduction to tf2 本部分是关于tf2简单介绍,比如tf2能做什么,并使用一个turtlesim的例子来显示tf2在多机器人中的一些能力.同时也包括一些工具的使用,比如tf2_ ...