本文共 8637 字,大约阅读时间需要 28 分钟。
Java Server Pages简称JSP,它和Servle一样也是SUN公司定义的一种用于开发动态web资源的技术。JSP的最大的特点在于:写JSP代码就像在写HTML但与HTML只能提供静态数据不同JSP允许开发人员在页面中嵌套java代码从而为用户提供动态数据。所以,可以形象的理解为:JSP = HTML + java
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>测试 原创作者:谷哥的小弟
博客地址:http://blog.csdn.net/lfdfhl
<% Date date=new Date(); out.println(date.toLocaleString()); %>
运行后如下图所示:
哇哈,看到了吧:我们在该index.jsp文件中简单地写了两行java代码,部署应用后浏览器中显示了java代码的运行结果。
看到这我们心里可能就有疑惑了:
嗯哼,带着这些疑问,我们继续学习。
其实,jsp之所以可以被web服务器执行并返回给客户端,这是因为jsp从本质上来讲它就是一个Servlet。何出此言呢?我们打开刚才项目在Tomcat的work文件夹,查看其运行后生成的文件,请看下图:
嗯哼,瞅见了没?依据原来的index.jsp文件生成了对应的index_class.java和index_jsp.class。再打开index_class.java瞅瞅:
public final class index_jspextends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent{ }
index_jsp继承自org.apache.jasper.runtime.HttpJspBase,那我们就继续来看看这个类:
public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage { }
嘿嘿,这个HttpJspBase又继承自HttpServlet。到了这里我们就明白了:jsp文件先会被翻译(转义)成一个HttpServlet子类的java文件再被编译成class文件;至此,jsp文件也就演变成了Servlet。
为了理解jsp的原理,我们来看看HttpJspBase的源码:
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的生命周期方法中会执行jsp相关的生命周期方法
继续看index_jsp.java的代码:
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_jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map 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("\r\n"); out.write("\r\n"); out.write(" \r\n"); out.write(" 测试 \r\n"); out.write(" \r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\t原创作者:谷哥的小弟
\r\n"); out.write("\t博客地址:http://blog.csdn.net/lfdfhl
\r\n"); out.write("\t"); Date date=new Date(); out.println(date.toLocaleString()); out.write("\r\n"); out.write("\r\n"); out.write(""); } 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的常用内置对象总结如下:
请注意:pageContext本身是一个域对象,但是它可操作其它三个域对象即request、session、application,例如它的如下方法:
setAttribute(String name,Object o,int scope);
getAttribute(String name,int scope);
removeAttribute(String name,int scope);
在这些方法中利用scope指定了操作的范围,其值可取为PageContext.PAGE_SCOPE 、PageContext.REQUEST_SCOPE 、PageContext.SESSION_SCOPE 、PageContext.APPLICATION_SCOPE
pageContext还有一个很强大的方法——findAttribute( ),它会自动依次从page、request、session、application中查找值,找到后就取出值并结束查找。
小结四个域对象:
PageContext、ServletRequest、HttpSession、ServletContext
PageContext : 它所存放的数据在当前页面有效,开发时使用较少
ServletRequest: 它所存放的数据在一次请求(转发)内有效 HttpSession: 它存放的数据在一次会话中有效,使用较多 ServletContext: 它所存放的数据在整个应用范围内都有效,但是因为其有效范围太大不利于数据隔离,应尽量少用我们知道:从本质上来讲,jsp就是一个Servlet。所以,JSP和Servlet都可以用于开发动态web资源。可是,如果让JSP既用java代码产生动态数据又做页面美化会导致代码难以维护;同理,如果让Servlet既处理逻辑又负责html的显示会导致程序代码可读性非常差。鉴于它们各自的特点,在长期的软件实践中,人们逐渐把Servlet作为web应用中的控制器组件来使用而把JSP作为数据显示模板来使用。
小结:
Servlet负责业务逻辑,即:获取表单数据、处理业务逻辑、分发与重定向
JSP负责数据的显示
请看如下示例:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>请您登陆 <% String msg = (String) request.getAttribute("msg"); if (msg != null){ out.print(msg); } %>
先写一个login.jsp,表单提交至如下Servlet
/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class DoLoginServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); if ("xzmly".equals(username) && "9527".equals(password)) { request.getSession().setAttribute("name", username); request.setAttribute("msg", "成功登录"); response.sendRedirect(request.getContextPath()+"/success.jsp"); } else { request.setAttribute("msg", "用户名或密码不正确,请重新登录"); request.getRequestDispatcher("/login.jsp").forward(request,response); } }}
在该Servlet中获取表单提交的数据并处理。如果未通过验证则请求转发至login.jsp,如果通过验证则跳转到如下success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>Welcome 欢迎您:<% String name = (String)session.getAttribute("name"); out.print(name); %>
这个例子很简单,但是体现了Servlet与JSP的分工及协作,比如数据的传递和页面的跳转。