自接触Java开发以来JSP在我的个人经验里一直扮演着重要的角色,一直以为能够熟练使用JSP就是很好的掌握了它,
但在一次面试过程当中被问及一个问题:“JSP 与 Servlet 的相同之处是什么”时,才发现自己对JSP工作的原理几乎一无所知。
现在我将与大家分享经过学习和整理后我所理解的JSP和Servlet,
本观点仅代表个人看法,大家可在评论里就这个问题畅所欲言,以求大家共同进步。
**首先JSP是什么呢?**
JSP是一种动态页面技术 java server page,其根本是一个简化的Servlet设计。
JSP诞生的目的就是为了让前端代码和后端代码分离在不同的文件中。
它实现了Html语法中的java扩展(以 <%, %>形式),JSP与Servlet一样,在服务器端执行。
通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览。
我们使用JSP的主要目的就是将表示逻辑从Servlet中分离出来,这样能够极大的简化开发。
那么以上解释具体应该怎么理解呢?我们首先来看一个编译后的Servlet(.java)文件。
jsp被变成了一个继承了org.apache.jasper.runtime.HttpJspBase的类。
查看jasper.jar里的HttpJspBase源码就可以发现HttpJspBase继承自javax.servlet.http.HttpServlet,
所以jsp就是一个servlet。
**Jsp文件**
<%@ 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 'index.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> This is my JSP page. </body> </html>
**Java文件**
/* * Generated by the Jasper component of Apache Tomcat * Version: JspCServletContext/1.0 * Generated at: 2017-02-24 03:08:52 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.*; import java.util.*; public final class index_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 javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } 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=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\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n<html>\r\n <head>\r\n <base href=\""); out.print(basePath); out.write("\">\r\n \r\n <title>My JSP 'index.jsp' starting page</title>\r\n\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n\t<meta http-equiv=\"expires\" content=\"0\"> \r\n\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n\t<!--\r\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n\t-->\r\n </head>\r\n \r\n <body>\r\n This is my JSP page. <br>\r\n </body>\r\n</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); } } }
大家可以看到,在这个文件里面有html代码,但这个文件是从.jsp文件转译成的.java文件,并不是手动编写的。
也就是说我们写的JSP文件并不是直接运行的,而是先会转译成.java文件。
做这个工作的正是JSP Container 即Tomcat服务器,它会将.jsp文件转译成.java文件,
然后再将.java文件编译成.class文件,.class文件会处理请求,返回响应,最后生成页面返回给客户端显示。
所以也可以理解为JSP文件就是Servlet文件,因为JSP文件是转换成Servlet文件才运行的。
没有JSP的话,就需要把静态页面的代码手动写到Servlet文件里,这时候其实就是将网页逻辑和网页设计写在了一起,
这样的开发复杂且效率比较低,所以JSP的出现就是将网页设计分离出来,简化开发。
既然是tomcat做的把jsp变为java的动作,那么java文件在哪呢?
可以看看tomcat的以下路径,就会发现我们发布在tomcat上的jsp被tomcat转化后java文件了。
tomcat\work\Catalina\localhost\工程名\org\apache\jsp\
当然tomcat的jasper.jar里有个org.apache.jasper.JspC类。
我们可以使用这个类手动来做jsp2java的动作。
借助ant,我们就可以调用JspC这个类。
执行jsp2java在outputDir设定的文件夹里就可以看到自己工程里jsp变成的java文件了。
<?xml version="1.0" encoding="GBK"?> <project name="WebApp Precompilation JSP to Java to Class to Jar" basedir="." default="help"> <target name="jsp2java"> <taskdef classname="org.apache.jasper.JspC" name="jsp2java"> <classpath id="jsp2java.classpath"> <fileset dir="D:/tomcat/bin"> <include name="*.jar"/> </fileset> <fileset dir="D:/tomcat/lib"> <include name="*.jar"/> </fileset> <fileset dir="D:/workspace/SSMv1.0/WebRoot/WEB-INF/lib"> <include name="*.jar"/> </fileset> </classpath> </taskdef> <!-- 注意JSP文件要设置为UTF-8编码 --> <jsp2java classpath="jsp2java.classpath" javaEncoding="UTF-8" validateXml="false" uriroot="D:/workspace/SSMv1.0/WebRoot" webXmlFragment="D:/workspace/SSMv1.0/WebRoot/WEB-INF/webJSP.xml" outputDir="D:/workspace/SSMv1.0/WebRoot/WEB-INF/JspC/src"/> </target> </project>
希望以上解释能对大家有所帮助!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于