在动态网页开发中,经常需要动态生成HTML内容,例如,一篇新闻报道的浏览次数需要动态生成。这时,如果使用Servlet来实现HTML页面数据的改变,需要调用大量的输出语句,导致程序非常臃肿。为了克服Servlet的这些缺点,退出了JSP技术。
JSP全名是Java Server Page,它是建立在Servlet规范之上的动态网页开发技术。在JSP文件中,HTML代码与Java代码共存,其中,HTML代码用来实现网页中静态内容的显示,Java代码用来实现网页中动态内容的显示,为了与普通HTML有所区别,JSP文件的扩展名为.jsp。
在该应用的WebRoot目录下创建一个JSP文件simple.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
当前访问时间是:
<%
out.print(new java.util.Date().toLocaleString());
%>
</body>
</html>
访问http://localhost:8080/HelloWeb/simple.jsp,会显示当前时间,刷新之后,内容会改变。每次在浏览器中查看其源文件,发现其内容却都不一样,这是因为simple.jsp是一个动态网页,它的动态效果实际上是由服务器程序实现的,如果是一个静态网页,那么每次查看源代码时,看到的内容都是相同的,这就是动态网页和静态网页的区别。
jsp文件包括HTML代码和Java代码,Java代码必须包含在<% %>之间
当用户第一次访问JSP页面时,该页面会被JspServlet翻译成一个Servlet源文件(simple_jsp.java),然后将源文件编译成.class文件。这两个文件在“Tomcat安装目录/work/Catalina/localhost/应用名/org/apache/jsp”这个目录下。
如果第二次没有更改jsp的话,会直接访问.class文件。
打开.java文件,其中有很多out.write语句,JSP本质上就是一个Servlet。
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class simple_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=UTF-8");
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\n");
out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n");
out.write("<title>Insert title here</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("\t当前访问时间是:\r\n");
out.write("\t");
out.print(new java.util.Date().toLocaleString());
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>");
} 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);
}
}
}
simple.jsp文件翻译后的Servlet类名为simple_jsp,它没有实现Servlet接口,但继承了org.apache.jasper.runtime.HttpJspBase类。
再Tomcat源文件中查看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.compiler.Localizer;
/**
* This is the super class of all JSP-generated servlets.
*
* @author Anil K. Vijendran
*/
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
private static final long serialVersionUID = 1L;
protected HttpJspBase() {
}
@Override
public final void init(ServletConfig config)
throws ServletException
{
super.init(config);
jspInit();
_jspInit();
}
@Override
public String getServletInfo() {
return Localizer.getMessage("jsp.engine.info");
}
@Override
public final void destroy() {
jspDestroy();
_jspDestroy();
}
/**
* Entry point into service.
*/
@Override
public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
_jspService(request, response);
}
@Override
public void jspInit() {
}
public void _jspInit() {
}
@Override
public void jspDestroy() {
}
protected void _jspDestroy() {
}
@Override
public abstract void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException;
}
从HttpJspBase源代码中可以看出,HttpJspBase类是HttpServlet的一个子类。由此可见,simple_jsp就是一个Servlet。
HttpJspBase类中的init方法被final关键字修饰,所以不能被子类重写,但其中调用了_jspInit()这个方法,而_jspInit()这个方法被其子类simple_jsp重写了,根据多态,到时候调用init方法就会调用子类的_jspInit()。
Servlet:控制器,重点编写Java代码逻辑(获取表单数据、处理业务逻辑、分发转向)
JSP:代码显示模板。重点在于显示数据。
让建立的JSP文件默认是UTF-8,Windows,Preferences,MyEclipse,Files and Editors,JSP
<%=i%>相当于out.print(i);
jsp和HTML中的代码改变不用重新启动服务器,.java需要
<%–jsp注释–%>这种注释,安全,省流量
当JSP页面被翻译成Servlet程序时,JSP中包含的脚本片段、表达式、模板元素都将转换为Servlet中_jspService()方法的程序代码。这时,JSP脚本片段中定义的变量都将成为_jspService()方法中的局部变量,而JSP脚本片段中定义的方法都将插入_jspService()方法,从而会出现程序的方法中再定义方法,这样的语法是错误的。为了解决这样的问题,在JSP技术中提供了声明,<%! %>这里边的代码将被翻译到Servlet的_jspService()方法之外,即在JSP声明中定义的都是成员变量、成员方法、静态方法、静态变量、静态代码块等。