背景:
问了一圈,每个人都一本正经的说,“jsp不需要编译,因为修改jsp之后,不需要重启,页面能立马生效”,恩,这个特性很像html,给大多数人造成了jsp不需要编译的假象,事实并非如此。
jsp是一种模板引擎,里面可以插入部分java代码,jsp里面的java代码如何得到想要的结果呢?直觉告诉我,它需要编译,否则,jvm如何读懂它?
答案:
让我们关注底层,看看原生servlet [参考runoob]是如何给前端返回页面的:
// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
// 扩展 HttpServlet 类
public class HelloWorld extends HttpServlet {
private String message;
public void init() throws ServletException
{
// 执行必需的初始化
message = "Hello World";
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置响应内容类型
response.setContentType("text/html");
// 实际的逻辑是在这里
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");
}
public void destroy()
{
// 什么也不做
}
}
没错,是在java代码中通过out.println()
打印到浏览器的。servlet是在java中嵌入html代码,而jsp可以理解为在html中嵌入java代码,其实jsp就是一种servlet,只不过更注重视图而已。
jsp运行时都要先转换成servlet,使用tomcat时会在tomcat安装目录下的work生成一系列的运行的项目文件夹,文件下面含有转译后的.java文件和编译后的.class文件。
jsp在首次请求时,会被转译为servlet并编译为class,如果不是第一次,则不会进行转译和编译,看起来有点像servelt的init()
生命周期[参考runoob],虽然没半毛钱关系,但是可以方便记忆。于是,我在本地的tomcat上做了实验,确实如我预想,项目编译完了,work目录下并不会有xxx_jsp.class
文件出现,但是一旦发起第一次请求,则会出现xxx_jsp.class
。
为什么不需要重新编译就可以立即生效?
我猜测是tomcat从字节码层面实时监控了class的变化。后来查阅资料,发现大差不差,tomcat有某种监听机制,能实时编译发生变化的jsp[参考此博客]。
结论:
jsp是一种更加注重视图的servlet,需要经过转译成servlet、编译成class两个步骤,且仅在第一次请求时发生。
参考:
https://blog.csdn.net/m0_37836194/article/details/76953475
http://www.runoob.com/servlet/servlet-life-cycle.html
https://blog.csdn.net/qq_24892029/article/details/51261732