概述

  在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. java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.String错误的解决方法

    mmobjectid是在Oracle数据库中对应的是Number类型的,在JavaBean中定义的是Long类型的. List<BigDecimal> mmobjidAllFromMars ...

  2. Spring4 mvc+maven 框架搭建(1)

    这篇博客其实很早就应该写,早在半年前,因为对SpringMVC感兴趣,便自学了一下Spring.一段时间的学习后,对Spring有了一个基本的了解,于是想着自己动手搭建一个SpringMvc的框架出来 ...

  3. C#:WebBrowser控件的使用教程及相关问题整理

    推荐阅读: C#WebBrowser控件使用教程与技巧收集--苏飞收集 C# WebBrowser强制在本窗口打开,禁止在新窗口打开 C# WebBrowser禁止在新窗口打开,强制在本窗口打开(多种 ...

  4. C#基础篇四数组

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace P01A ...

  5. 【Java初探02】——Java语言基础

    本篇博文就Java语言的一些基本元素进行一些记录和阐述,主要讲解一下Java语言的一些基本构成元素和Java的主类结构. Java语言基础的大致组成 java主类结构 基本的数据类型 变量与常量 运算 ...

  6. Vue笔记:使用node开发vue入门实例

    安装NPM 首先在命令终端输入 npm -v 检测是否安装 npm.如果没有,按照下面教程进行安装. 下载地址: nodejs中文网 到官网下载自己系统对应的版本,这里我们下载Windows系统的64 ...

  7. Mysql字符串转换为整型

    使用Convert(字段名, 类型)方法 SELECT CONVERT(filedName, UNSIGNED INTEGER) ;

  8. PTA (Advanced Level) 1005 Spell It Right

    Spell It Right Given a non-negative integer N, your task is to compute the sum of all the digits of  ...

  9. Windows Mobile设备操作演示准备工作小记

    公司最近为PDA开发了一款作业程序,我在工作中常常需要将操作过程通过电脑上设影出来为客户讲解使用方法.本文记录了相关的准备工作. 1. 微软嵌入式操作系统体系 RTOS: Embedded Real ...

  10. 24.ArrayBuffer

    ArrayBuffer ArrayBuffer ArrayBuffer对象.TypedArray视图和DataView视图是 JavaScript 操作二进制数据的一个接口.这些对象早就存在,属于独立 ...