整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

深入了解 JSP 的运行过程

深入了解 JSP 的运行过程

么是 JSP?

JSP(全称JavaServer Pages)是由 Sun Microsystems 公司主导创建的一种==动态==网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成 HTML、XML 或其他格式文档的 Web 网页,然后返回给请求者。

JSP 主要作用

  • 代替 Servlet 程序回传 HTML 页面的数据。

接下来我们去看看 JSP 是如何实现代替 Servlet 的。

JSP 在本质上就是一个 Servlet 程序?

如果我们访问一个 Servlet 程序,让它返回给我们一个前端页面,那么就需要在 JavaWEB 项目下编写一个 HelloServlet 程序:

package com.example.demo;

import java.io.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

@WebServlet("/hello-servlet")
public class HelloServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf8");
        // HelloWorld 页面
        PrintWriter out=response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html lang='en'>");
        out.println("<head>");
        out.println("<meta charset='UTF-8'>");
        out.println("<title>Title</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Hello World!</h1>");
        out.println("</body>");
        out.println("</html>");
    }

}

当我们启动程序,在浏览器访问http://localhost:8080/hello-servlet 时,浏览器会回传显示一个简单的页面

按 F12 进入开发者模式,可以看到 Servlet 程序响应回传了我们在Servlet 程序中拼接的 html 代码。



那么到这里还不能让我们明白 JSP 就是一个 Servlet,再往下看。

我们创建一个JSP 文件 index.jsp,这样启动项目时,自动弹出的首页就是我们的 index.jsp 页面。

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>JSP - Hello World</title>
</head>
<body>
<h1><%="Hello World!" %></h1>
</body>
</html>

我们启动项目



从控制台找到项目部署路径

C:\Users\Jie\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\38d57dfc-4429-4e47-8912-74706f5fff5a

我们直接访问此路径,可以看到目录下存在的文件。



进入work\Catalina\localhost\ROOT\org\apache\jsp 目录,可以看到存在的两个文件【index_jsp.java】和【index_jsp.class】



接着我们将这两个文件删除,同时在浏览器进行刷新页面,可以看到目录下新增了我们刚删除的两个文件【index_jsp.java】和【index_jsp.class】



接着,我们使用 Notepad++ 打开【index_jsp.java】文件,查看编译之后的 Java 文件代码。



可以看到 index.jsp 中 HTML 部分的代码被嵌入在 java 代码中,这和我们一开始在 HelloServlet 中拼接的 HTML 代码一摸一样。

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 {
   /*something*/                  
}

查看源码我们可以看见 index_jsp 继承了 org.apache.jasper.runtime.HttpJspBase 类,

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 org.apache.jasper.Constants;
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 {
    /*something*/
}

我们继续查看 org.apache.jasper.runtime.HttpJspBase 类的源码,可以发现,HttpJspBase 类直接继承了 HttpServlet类。也就是说,JSP 翻译出来的 index_jsp.java 类,它间接了继承 HttpServlet 类,这和我们直接编写 Servlet 程序继承 HttpServlet 类 是一样的。

因此 JSP 本质就是一个 Servlet 程序。它可以省掉不少我们在 Servlet 中拼接 HTML 代码的时间。不过随着前后端分离的出现,JSP 也逐渐被淘汰。

JSP的执行过程

当我们第一次访问 JSP 页面的时候,Tomcat 服务器主要会帮我们完成:

  1. 把 JSP 页面翻译成为一个 .java 源文件
  2. 对 .java 源文件编译成为 .class 字节码文件
  3. 执行 .class 字节码文件返回结果

当我们第二次访问 JSP 页面的时候,如果未做更改,则使用上次编译的 .class 文件;若修改过,则重新编译。

建工程

File>New>Web Project


填写项目名称Project Name,举例为andylife,这里使用的是默认存储路径,如需修改,把下面Use default location前面的勾去掉,并在Directory填写自己的地址


设置完成后点击Finish,新建完成

编写内容

打开WebRoot目录下的index.jsp,把编码改为utf-8


网页修改内容,显示日期时间源码:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%

String path=request.getContextPath();

String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<html>

<body>

<%

//设置刷新页面的时间,每隔1秒钟刷新一次

response.setHeader("refresh", "10");

%>

当前的系统时间是:

<%

//输出当前时间

Calendar now=Calendar.getInstance();

out.print(now.get(Calendar.YEAR) + "年");

out.print(now.get(Calendar.MONTH) + 1 + "月");

out.print(now.get(Calendar.DATE) + "日");

out.print(now.get(Calendar.HOUR_OF_DAY) + "时");

out.print(now.get(Calendar.MINUTE) + "分");

out.print(now.get(Calendar.SECOND) + "秒 ");

out.print("星期");

switch (now.get(Calendar.DAY_OF_WEEK)) {

case 1:

out.print("日");

break;

case 2:

out.print("一");

break;

case 3:

out.print("二");

break;

case 4:

out.print("三");

break;

case 5:

out.print("四");

break;

case 6:

out.print("五");

break;

case 7:

out.print("六");

}

out.print(""+"<hr>");

out.print("ID Things need to be done IF DAILY "+"<br>");

%>

</body>

<body>

<%

out.print(""+"<hr>");

%>

</body>

</html>

运行

把页面部署到Tomcat上

点击ADD,然后选择我们的Tomcat服务器,点击Finish,然后点OK





点击旁边图标的小三角形,选择服务器,并运行

当我们在控制台看到此信息时,服务器就开启成功了


前端浏览

在浏览器输入网址:http://localhost:8080/life/index.jsp

它表示的是,在本地8080端口下,life中的index.jsp

1),模板文件add_jsp_.ftl

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%
String childPath=request.getContextPath();
String basePath=request.getScheme() + "://"
	+ request.getServerName() + ":" + request.getServerPort() + childPath +"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title></title>
	<%@ include file="/pub/scripts.jsp"%>

    <script type="text/javascript">

		function submit_save() {

			var varName_=$("#name_").val();
			if(varName_==null || varName_=='') {
			    alert("请先输入名称!")
			    return false;
			} else {
                $("#addForm").submit();
			}
        }
    </script>
    
  </head>
  <body>
  		
		<!-- 标题区域 -->
		<div class="tleBg">
			<div class="title">
				<span class="txt"> <em></em><#list mapDataTableComment as listItmCom > ${listItmCom.columnComment} </#list>- 新增
				</span> <a href="javascript:;" class="search-hide"></a>
			</div>
			<div class="clr"></div>
		</div>
  		
  		<!-- 查询维度区域 -->
		<div class="t_list" id="addtable">
			<form name="addForm" id="addForm" action="<%=childPath %>/testT00_userConter/testT00_userAddSave" method="post">

				<table border="0" cellspacing="0" width="100%" cellpadding="0" class="t_list_1">
					<tbody>
					
					
					<#list mapDataList as listItm >
						
						<tr style="line-height: 36px;">
							<td width="15%">
								 
							</td>
							<td width="20%" class="text" style="text-align: right;">
								${listItm.columnComment}:
							</td>
							<td>
								<input type="text" id="${listItm.columnName}" name="${listItm.columnName}" style="width: 300px;" class="inputStyle" value="原左大括<#list mapDataTableComment as listItmCom > ${listItmCom.columnName} </#list>.${listItm.columnName}原右大括" />
							</td>
							<td width="15%">
								 
							</td>
						</tr>
					</#list>

					
						<tr>
							<td width="15%">
								 
							</td>
							<td width="20%" class="text" style="text-align: right;">
								 
							</td>
							<td>
								<input type="button" id="btn_add" value="保 存" class="t_button_gray" onclick="return submit_save();" />
								<input type="reset" id="btn_rest" value="重 置" class="t_button_gray" />
							</td>
							<td width="15%">
								 
							</td>
						</tr>

					</tbody>
				</table>
			</form>
		</div>
  		
  </body>
</html>

(2),根据模板及表元数据生成新增jsp页面

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @date: 2022/12/03 08:27
 * @desc: 测试入口
 */
public class TestCls {

    public static void main(String[] args) throws Exception {
        new TestCls().outTemplate();
    }

    // 输出到模板
    private void outTemplate() throws Exception {

        Configuration configuration=new Configuration();
        configuration.setDirectoryForTemplateLoading(new File("F:\\xbl\\myResource\\temp_test_"));
        Template template=configuration.getTemplate("add_jsp_.ftl");

        Map<String, List<EntryInfoPo>> dataMap=new HashMap<String, List<EntryInfoPo>>();
        List<EntryInfoPo> listEntryInfo=new ArrayList<EntryInfoPo>();
        listEntryInfo=testMetaAddComment();
        dataMap.put("mapDataList", listEntryInfo );

        // 表注释
        dataMap.put("mapDataTableComment", testTableComment());

        Writer outputWriter=new OutputStreamWriter(new FileOutputStream(new File("F:\\xbl\\myResource\\temp_test_\\add_.jsp") ) );
//        Writer outputWriter=new OutputStreamWriter(System.out );
        template.process(dataMap, outputWriter);
        System.out.println("输出完成!");
        outputWriter.close();
    }

    // 表注释
    private List<EntryInfoPo> testTableComment() throws Exception {

        List<EntryInfoPo> listTableComment=new ArrayList<EntryInfoPo>();
        EntryInfoPo entryInfoPo=new EntryInfoPo();
        entryInfoPo.setColumnName("testT00_userDto");
        entryInfoPo.setColumnComment("用户管理");
        listTableComment.add(entryInfoPo);
        return listTableComment;
    }

    private List<EntryInfoPo> testMetaAddComment() throws Exception {

        List<EntryInfoPo> listEntryInfoPo=new ArrayList<EntryInfoPo>();
        Connection connection=getDataBaseConnection();
        Statement statement=connection.createStatement();
        ResultSet resultSet=statement.executeQuery("show full columns from t00_user ");
        while (resultSet.next()) {

            String columnComment=resultSet.getString("Comment");
            String columnName=resultSet.getString("Field");
            EntryInfoPo entryInfoPo=new EntryInfoPo();
            entryInfoPo.setColumnName(columnName);
            entryInfoPo.setColumnComment(columnComment);
            listEntryInfoPo.add(entryInfoPo);
        }
        return listEntryInfoPo;
    }
    private Connection getDataBaseConnection() throws Exception {
        // 连接数据库
        Class.forName("com.mysql.jdbc.Driver");
        String databaseUrl="jdbc:mysql://127.0.0.1:3306/grcdb05?useUnicode=true&characterEncoding=utf8";
        Connection connection=DriverManager.getConnection(databaseUrl, "root", "root");
        return connection;
    }
}

(3),创建一个空文件add_.jsp,执行步骤(2)能生成页面