概述

  在Servlet中编写HTML太麻烦了,应该使用JSP。JSP中可以直接编写HTML,使用指示、声明、脚本(scriptlet)等元素来堆砌各种功能,但JSP最后还是会被容器转译为Servlet源代码、自动编译为.class文件、载入.class文件,然后生成Servlet对象。
  在第一次请求JSP时,容器会进行转译、编译与加载的操作,所以第一次请求JSP页面会慢很多。


源码分析

  若使用Tomcat 7或Glassfish v3作为Web容器,最后由容器转译后的Servlet类是继承自HttpJspBase类,而HttpJspBase又继承了HttpServlet。
  下面是HttpJspBase类的源码,这个类的源码可以在Tomcat的lib目录下的 jasper.jar\org\apache\jasper\runtime 这个文件夹找到。

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.compiler.Localizer; public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
private static final long serialVersionUID = 1L;
protected HttpJspBase() {
}
public final void init(ServletConfig config) throws ServletException {
super.init(config);
this.jspInit();
this._jspInit();
}
public String getServletInfo() {
return Localizer.getMessage("jsp.engine.info");
}
public final void destroy() {
this.jspDestroy();
this._jspDestroy();
}
public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this._jspService(request, response);
}
public void jspInit() {}
public void _jspInit() {}
public void jspDestroy() {}
protected void _jspDestroy() {}
public abstract void _jspService(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException;
}

  观察HttpJspBase的源代码,可以看到,Servlet的init()方法中调用了jspInit()与_jspInit();Servlet的destroy()方法中调用了jspDestroy()与_jspDestroy()方法;service()方法中调用了_jspService()方法。
  _jspInit()、_jspDestroy()与_jspService()方法名称上有个下划线,表示这些方法是由容器转译时维护,不应该重新定义这些方法。如果想要做些JSP初始化或收尾动作,则应定义jspInit()或jspDestroy()方法。

  观察HttpJspBase的源代码,还可以看到,它继承了HttpServlet。但没有重写其doGet、doPost方法;只重写了HttpServlet参数为HttpServletRequest和HttpServletResponse的service方法,然后调用自己定义的抽象方法_jspService()。再观察jsp转译后的servlet,它的_jspService()方法内部并没有判断get、post方法,所以jsp既可以使用post也可以使用get来发出请求。


Servlet 改写为 JSP

将要被改写的Servlet源码:

package com.test;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set; @WebServlet("/books")
public class ListBookmark extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset=\"UTF-8\">");
out.println("<title>觀看線上書籤</title>");
out.println("</head>");
out.println("<body>");
out.println("<table style=\"text-align: left; width: 100%;\" border=\"0\" >");
out.println(" <tbody>");
out.println("<tr>");
out.println("<td style=\"background-color: rgb(51, 255, 255);\">书名</td>");
out.println("<td style=\"background-color: rgb(51, 255, 255);\">分类</td>");
out.println("</tr>"); Map<String, String> bookMap = new HashMap<String, String>();
bookMap.put("三国演义", "小说");
bookMap.put("资治通鉴", "历史");
bookMap.put("窦娥冤", "戏剧");
Set<Map.Entry<String, String>> entries = bookMap.entrySet();
for (Map.Entry<String, String> entry : entries) {
out.println("<tr>");
out.println("<td>" + entry.getKey() + "</td>");
out.println("<td>" + entry.getValue() + "</td>");
out.println("</tr>");
} out.println("</tbody>");
out.println("</table>");
out.println("</body>");
out.println("</html>");
out.close();
}
}

手动改写好的JSP源码:

<%@page contentType="text/html; charset=GBK" pageEncoding="UTF-8" %>
<%@page import="javax.servlet.*, java.io.PrintWriter, java.util.HashMap, java.util.Map, java.util.Set" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>在线书籍</title>
</head>
<body>
<table style="text-align:left; width:100%;" border="0">
<tbody>
<tr>
<td style="background-color: rgb(51, 255, 255);">书名</td>
<td style="background-color: rgb(51, 255, 255);">分类</td>
</tr>
<%
Map<String, String> bookMap = new HashMap<String, String>();
bookMap.put("三国演义", "小说");
bookMap.put("资治通鉴", "历史");
bookMap.put("窦娥冤", "戏剧");
Set<Map.Entry<String, String>> entries = bookMap.entrySet();
for (Map.Entry<String, String> entry : entries) {
%>
<tr>
<td><%= entry.getKey() %></td>
<td><%= entry.getValue()%></td>
</tr>
<%
}
%>
</tbody>
</table>
</body>
</html>

运行结果完全一致。

index_jsp.java源文件:

在IDEA中,JSP转译为Servlet后的源代码和进一步编译后的字节码文件可以在 target/tomcat/work/Tomcat/localhost/_/org/apache/jsp/ 这个文件夹下找到。

/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.47
* Generated at: 2018-12-05 16:02:28 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 javax.servlet.*;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set; 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=GBK");
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("\n");
out.write("\n");
out.write("<!DOCTYPE html>\n");
out.write("<html>\n");
out.write("<head>\n");
out.write(" <meta charset=\"UTF-8\">\n");
out.write(" <title>在线书籍</title>\n");
out.write("</head>\n");
out.write("<body>\n");
out.write("<table style=\"text-align:left; width:100%;\" border=\"0\">\n");
out.write(" <tbody>\n");
out.write(" <tr>\n");
out.write(" <td style=\"background-color: rgb(51, 255, 255);\">书名</td>\n");
out.write(" <td style=\"background-color: rgb(51, 255, 255);\">分类</td>\n");
out.write(" </tr>\n");
out.write(" "); Map<String, String> bookMap = new HashMap<String, String>();
bookMap.put("三国演义", "小说");
bookMap.put("资治通鉴", "历史");
bookMap.put("窦娥冤", "戏剧");
Set<Map.Entry<String, String>> entries = bookMap.entrySet();
for (Map.Entry<String, String> entry : entries) { out.write("\n");
out.write(" <tr>\n");
out.write(" <td>");
out.print( entry.getKey() );
out.write("</td>\n");
out.write(" <td>");
out.print( entry.getValue());
out.write("</td>\n");
out.write(" </tr>\n");
out.write(" "); } out.write("\n");
out.write(" </tbody>\n");
out.write("</table>\n");
out.write("</body>\n");
out.write("</html>\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { 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);
}
}
}

JSP响应内容、字符编码设置

jsp源文件:    <%@page contentType="text/html; charset=GBK" pageEncoding="UTF-8" %>
index_jsp.java:  response.setContentType("text/html; charset=GBK");

jsp源文件:    <%@page contentType="text/html" pageEncoding="UTF-8" %>
index_jsp.java:  response.setContentType("text/html;charset=UTF-8")

jsp源文件:    <%@page contentType="text/html;" pageEncoding="UTF-8" %>
index_jsp.java:  response.setContentType("text/html;;charset=UTF-8")

前两种方法都可以,第三种方法的index_jsp.java里多个一个分号 response.setContentType("text/html;;charset=UTF-8")

pageEncoding属性用于告诉容器使用UTF-8读取.jsp转译为.java,然后编译时也使用UTF-8,并且如果在contentType属性里没有指定字符编码的情况下设置内容类型附加的charset也为UTF-8。

JSP源码、改写Servlet为JSP、查看转译成为Servlet的文件、JSP字符编码设置的更多相关文章

  1. [置顶] 我的Android进阶之旅------>如何将Android源码导入Eclipse中来查看(非常实用)

    Android源码下载完成的目录结构如如所示: step1:将.classpath文件拷贝到源代码的根目录 Android源码支持多种IDE,如果是针对APP层做开发的话,建议大家使用Eclipse开 ...

  2. 我的Android进阶之旅------>如何将Android源码导入Eclipse中来查看(非常实用)

    Android源码下载完成的目录结构如如所示: step1:将.classpath文件拷贝到源代码的根目录 Android源码支持多种IDE,如果是针对APP层做开发的话,建议大家使用Eclipse开 ...

  3. 《AndroidStudio导入安卓源码-idegen》---可方便查看安卓源代码

    idegen是Android源码中的一个模块,需要编译一下.生成一个jar包.然后再进行构建生成AndroidStudio配置相关文件. > 什么是idegen 要将Android系统源代码工程 ...

  4. eclipse设置新建jsp文件默认字符编码为utf-8

    在使用Eclipse开发中,编码默认是ISO-8859-1,不支持中文.这样我们每次新建文件都要手动修改编码,非常麻烦.其实我们可以设置文件默认编码,今后再新建文件时就不用修改编码了. 1.打开Ecl ...

  5. python基础之 列表、元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码

    本节内容 列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作 定义列表 ...

  6. 关于 Eclipse中的Web项目 部署的文件位置 查看jsp源码的部署位置

    使用 eclipse 开发web项目 会默认 部署在 工作目录下: .metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps 在这里 ...

  7. 放出一批学生管理系统jsp源码,部分有框架

    基于jsp+struts 2的学生管理系统eclipse - 源码码头   https://www.icodedock.com/article/25.html 基于jsp+mysql的JSP学生成绩管 ...

  8. java网络考试系统的设计与实现 jsp 源码

    开发环境: Windows操作系统开发工具:MyEclipse/Eclipse + JDK+ Tomcat + MySQL 数据库 项目简介: 网络考试系统主要用于实现高校在线考试,基本功能包括:自动 ...

  9. eclipse查看jdk源码,及反编译查看

    jdk中的包: dt.jar是关于运行环境的类库,主要是swing的包 tools.jar是关于一些工具的类库 rt.jar包含了jdk的基础类库,也就是你在java doc里面看到的所有的类的cla ...

随机推荐

  1. Linux的mv 命令

    mv 命令的10个例子 1.移动文件 移动文件时需要注意的是文件的源地址和目标地址必须不同.这里有个例子,想要将file_1.txt文件从当前目录移动到其它目录,以/home/pungki/为例,语法 ...

  2. Storm中的定时任务

    1.全局定时器 import java.util.Map; import backtype.storm.Config; import backtype.storm.Constants; import ...

  3. VMware虚拟机克隆Linux(CentOS)系统后找不到eth0网卡的问题(图文详解)

     问题现象: 有时候,会使用VMware虚拟机的的克隆功能,快速的复制已安装好的Linux系统. 可是克隆完之后,会发现没有eth0网卡. 解决办法: 1.编辑/etc/udev/rules.d/70 ...

  4. java学习-Comparable<Integer>接口方法的实现

    基本数据类型的包装类Integer, Float, Double,Long,Byte等都实现的Comparable接口,用于列表List或数组arrays的排序 Comparable<Integ ...

  5. ASP.NET 数据绑定到列表控件

    <div> <asp:ListBox ID="ListBox1" runat="server"></asp:ListBox> ...

  6. gulp学习笔记-怎样做一个gulp-demo

    第一步:在文件夹内:鼠标右键+shift  选择提示窗口中的  在此处打开命令窗口  第二步:创建npm的配置文件,在命令窗口中输入 npm init 进行npm的配置 npm init gulp-d ...

  7. 【IT笔试面试题整理】链表

    如何准备 Linked list questions are extremely common These can range from simple (delete a node ina linke ...

  8. WinForm窗体上两个panel,怎么实现一个panel固定漂浮在另一个panel之上

    问题:winform窗体,要实现一个panel漂浮在另一个panel之上,但是运行的时候移动鼠标或者其他操作,上面那个panel就会消失?即只能显示一个panel. 原因:在窗体上拖放控件肉眼观察是平 ...

  9. JS DOM操作 函数 事件 阻止事件冒泡

    一 函数 1.字符串函数 s.tolowerCase( ):    -- 变小写 s.toupperCase( ):   -- 变大写 s.substr( 2 , 8 ):     -- 截取     ...

  10. MyCat安装配置

    Mycat : 数据库分库分表中间件 http://www.mycat.io/ mycat运行需要JVM,所以先安装java环境,JDK1.7以上.数据库采用mysql5.7,或者8.0 下载 下载地 ...