JavaWeb之JSP原理
1.为什么需要JSP?
在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变。如果使用Servlet程序来输出只有局部内容需要改动的网页,其中所有的静态内容也需要程序员用java程序代码产生,整个Servlet程序的代码将非常臃肿,编写和维护都非常困难。对大量静态内容的美工设计和相关HTML语句的编写,并不是程序员所要做的工作,程序员对此也不一定在行。网页美工设计和制作人员不懂java编程,更是无法完成这样的工作。为了弥补Servlet的缺陷,SUN公司在Servlet的基础上推出了JSP技术作为解决方案。
2.什么是JSP?
JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。
3.如何在MyEclipse中运行jsp文件?
jsp文件一般放在WebRoot文件夹下,可以在WebRoot目录下新建一个文件用来放jsp文件。例如如下的文件目录:
示例中新建了一个helloWorld.jsp文件,Jsp技术允许在页面中嵌套java代码,规定java代码写在<% %>内部,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'helloWorld.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> </head> <body>
<%
Date date=new Date();
System.out.println(date);
%>
</body>
</html>
.jsp文件放在WebRoot目录下的非WEB-INF文件夹下是不需要在web.xml中进行配置的。右击直接运行就可以。
为了减少风险,可以把jsp文件移到WEB-INF 目录下。基于Servlet的声明,WEB-INF不作为Web应用的公共文档树的一部分。因此,WEB-INF 目录下的资源不是为客户直接服务的。我们仍然可以使用WEB-INF目录下的JSP页面来提供视图给客户,客户却不能直接请求访问JSP。放在WEB-INF 目录下需要在web.xml中进行配置。配置方法与servlet的配置一样,只不过是将<servlet-class></servlet-class>标签改为<jsp-file></jsp-file>,标签内填的内容是“/jsp文件所在的文件夹名/jsp文件名”。配置后运行,右击jsp文件,Run As MyEclipse Server Application。运行后显示结果如下:
4.JSP原理
4.1 web服务器是如何调用并执行一个jsp页面的?
浏览器向服务器发请求,不管访问的是什么资源,其实都是在访问Servlet,所以当访问一个jsp页面时,其实也是在访问一个Servlet,服务器在执行jsp的时候,首先把jsp翻译成一个Servlet,所以我们访问jsp时,其实不是在访问jsp,而是在访问jsp翻译过后的那个Servlet,比如上面的helloWorld.jsp文件,当我们通过浏览器访问helloWorld.jsp时,服务器首先将helloWorld.jsp翻译成一个helloWorld.class,(文件路径可以参考:E:\MyEclipseWorkSpace\.metadata\.me_tcat85\work\Catalina\localhost\MyWebProject\org\apache\jsp\jspTest,其中MyEclipseWorkSpace为项目所在的工程目录),helloWorld.class的源代码文件helloWorld.java的代码如下:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.5.9
* Generated at: 2018-10-12 09:24:04 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.jspTest; import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*; public final class helloWorld_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("java.util");
_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=ISO-8859-1");
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');
out.write('\n'); String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; out.write("\r\n");
out.write("\r\n");
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <base href=\"");
out.print(basePath);
out.write("\">\r\n");
out.write(" \r\n");
out.write(" <title>My JSP 'helloWorld.jsp' starting page</title>\r\n");
out.write(" \r\n");
out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n");
out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
out.write("\t<!--\r\n");
out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
out.write("\t-->\r\n");
out.write("\r\n");
out.write(" <script>\"undefined\"==typeof CODE_LIVE&&(!function(e){var t={nonSecure:\"51550\",secure:\"51555\"},c={nonSecure:\"http://\",secure:\"https://\"},r={nonSecure:\"127.0.0.1\",secure:\"gapdebug.local.genuitec.com\"},n=\"https:\"===window.location.protocol?\"secure\":\"nonSecure\";script=e.createElement(\"script\"),script.type=\"text/javascript\",script.async=!0,script.src=c[n]+r[n]+\":\"+t[n]+\"/codelive-assets/bundle.js\",e.getElementsByTagName(\"head\")[0].appendChild(script)}(document),CODE_LIVE=!0);</script></head>\r\n");
out.write(" \r\n");
out.write(" <body data-genuitec-lp-enabled=\"false\" data-genuitec-file-id=\"wc1-1\" data-genuitec-path=\"/MyWebProject/WebRoot/jspTest/helloWorld.jsp\">\r\n");
out.write(" "); Date date=new Date();
System.out.println(date); out.write("\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\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);
}
}
}
我们可以看到,helloWorld_jsp这个类是继承 org.apache.jasper.runtime.HttpJspBase这个类的,通过查看Tomcat服务器的源代码,如下所示:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.apache.jasper.runtime; 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; /**
* This is the super class of all JSP-generated servlets.
*
* @author Anil K. Vijendran
*/
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;
}
HttpJspBase类是继承HttpServlet的,所以HttpJspBase类是一个Servlet,而helloWorld_jsp又是继承HttpJspBase类的,所以helloWorld_jsp类也是一个Servlet,所以当浏览器访问服务器上的helloWorld.jsp页面时,其实就是在访问helloWorld.jsp这个Servlet,helloWorld_jsp这个Servlet使用_jspService这个方法处理请求。
也就是说,web容器(Servlet引擎)接收到以.jsp为扩展名的URL的访问请求时,它将该访问请求交给JSP引擎去处理。每个JSP页面在第一次被访问时,JSP引擎将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class文件,然后再用web容器(Servlet引擎)像调用普通的Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。
4.2 Jsp页面中的html排版标签是如何被发送到客户端的?
浏览器接受到的这些数据(右击该网页,点击查看网页源码):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="http://localhost:8080/MyWebProject/"> <title>My JSP 'helloWorld.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> <script>"undefined"==typeof CODE_LIVE&&(!function(e){var t={nonSecure:"51550",secure:"51555"},c={nonSecure:"http://",secure:"https://"},r={nonSecure:"127.0.0.1",secure:"gapdebug.local.genuitec.com"},n="https:"===window.location.protocol?"secure":"nonSecure";script=e.createElement("script"),script.type="text/javascript",script.async=!0,script.src=c[n]+r[n]+":"+t[n]+"/codelive-assets/bundle.js",e.getElementsByTagName("head")[0].appendChild(script)}(document),CODE_LIVE=!0);</script></head> <body data-genuitec-lp-enabled="false" data-genuitec-file-id="wc1-1" data-genuitec-path="/MyWebProject/WebRoot/jspTest/helloWorld.jsp"> </body>
</html>
都是在_jspService方法中使用如下的代码输出给浏览器的:
out.write('\r');
out.write('\n'); String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; out.write("\r\n");
out.write("\r\n");
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <base href=\"");
out.print(basePath);
out.write("\">\r\n");
out.write(" \r\n");
out.write(" <title>My JSP 'helloWorld.jsp' starting page</title>\r\n");
out.write(" \r\n");
out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n");
out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
out.write("\t<!--\r\n");
out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
out.write("\t-->\r\n");
out.write("\r\n");
out.write(" <script>\"undefined\"==typeof CODE_LIVE&&(!function(e){var t={nonSecure:\"51550\",secure:\"51555\"},c={nonSecure:\"http://\",secure:\"https://\"},r={nonSecure:\"127.0.0.1\",secure:\"gapdebug.local.genuitec.com\"},n=\"https:\"===window.location.protocol?\"secure\":\"nonSecure\";script=e.createElement(\"script\"),script.type=\"text/javascript\",script.async=!0,script.src=c[n]+r[n]+\":\"+t[n]+\"/codelive-assets/bundle.js\",e.getElementsByTagName(\"head\")[0].appendChild(script)}(document),CODE_LIVE=!0);</script></head>\r\n");
out.write(" \r\n");
out.write(" <body data-genuitec-lp-enabled=\"false\" data-genuitec-file-id=\"wc1-1\" data-genuitec-path=\"/MyWebProject/WebRoot/jspTest/helloWorld.jsp\">\r\n");
out.write(" "); Date date=new Date();
System.out.println(date); out.write("\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\n");
在jsp中编写的java代码和html代码都会被翻译到_jspService方法中去,在jsp中编写的java代码会原封不动地翻译成java代码,如<%out.print("Hello Jsp");%>直接翻译成out.print("Hello Jsp");,而HTML代码则会翻译成使用out.write("<html标签>\r\n");的形式输出到浏览器。在jsp页面中编写的html排版标签都是以out.write("<html标签>\r\n");的形式输出到浏览器,浏览器拿到html代码后才能够解析执行html代码。
4.3 Jsp页面中的java代码服务器是如何执行的?
在jsp中编写的java代码会被翻译到_jspService方法中去,当执行_jspService方法处理请求时,就会执行在jsp编写的java代码了,所以Jsp页面中的java代码服务器是通过调用_jspService方法处理请求时执行的。
wx搜索“程序员考拉”,专注java领域,一个伴你成长的公众号!
JavaWeb之JSP原理的更多相关文章
- javaweb学习总结(十四)——JSP原理
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- javaWeb学习总结(8)- JSP原理
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- javaweb(十四)——JSP原理
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- javaweb学习总结(十四)——JSP原理(转)
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- java web学习总结(十四) -------------------JSP原理
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- JavaWeb---总结(十四)JSP原理
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- JSP 原理
参考文献:http://www.cnblogs.com/xdp-gacl/p/3764991.html 一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都 ...
- java web 学习十四(JSP原理)
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- javaweb 与jsp页面的交互流程 (初次接触时写)
javaweb 与jsp页面的交互流程 javaweb项目目录 1. javaweb项目的一般目录: 2. jsp 页面一般情况下放在 top(前台页面) back(后台页面) 3. 后台代码 放在s ...
随机推荐
- SSO单点登录入门
1,SSO简介 SSO(Single Sign-On,单点登录)是身份管理中的一部分.SSO 的一种较为通俗的定义是:SSO 是指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过 ...
- centos 安装 Pip 的方法总结
转自https://blog.csdn.net/u014236259/article/details/75212659 在我们安装Python后,如果未安装包管理工具pip,此时需要自己手动安装: 方 ...
- Jmeter后置处理器之JSON Extractor
一.使用场景 json extractor后置处理器用在返回格式为json的HTTP请求中,用来获取返回的json中的某个值.并保存成变量供后面的请求进行调用或断言等. 二.使用方法 步骤一:选择HT ...
- P3267 [JLOI2016/SHOI2016]侦察守卫
$ \color{#0066ff}{ 题目描述 }$ 小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的.换句话说,游戏的地图是一棵有N个节点的 ...
- Linux-Web应用服务性能测试初探
一.服务端与客户端的准备工作 对于服务器最想要的数据就是,每秒支持的并发数,以及相应的内存CPU使用情况. 服务端需要设置最大打开描述符的限制(以支持创建大量的socket),配置socket参数.客 ...
- python高级(一)—— python数据模型(特殊方法)
本文主要内容 collections.namedtuple __getitem__ 和 __len__ __repr__和__str__ __abs__.__add__和__mul__ __bool_ ...
- mocha测试框架
中文翻译文档:https://www.jianshu.com/p/9c78548caffa 阮一峰:http://www.ruanyifeng.com/blog/2015/12/a-mocha-tut ...
- 大数据平台-修改主机名及ssh免密码登录
一.查看服务器初始配置: 1.总核数 = 物理CPU个数 X 每颗物理CPU的核数 2.总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数cat /pr ...
- abp部署端口和域名映射配置
前引 apb部署 后端服务9900端口,域名访问地址是:http://nihao-api.hellow.com: 前端4200端口,域名访问地址是:http://nihao.hellow.com: 前 ...
- [短期持续更新]Codeforces 构造题一览
说实话我觉得做这种题很没意思(不够硬核), 可是人有短板终究是要补的...起码这种类型补起来相对简单 所以还是把先前准备好的专题放下吧,做点实现上比较休闲的题 ps.为了精简篇幅,代码全部丢到ubun ...