JSP&Servlet6(一) --- 初探JSP

来源:互联网 发布:微网站系统源码 编辑:程序博客网 时间:2024/06/05 07:44

前面总结完了Servlet相关的基础知识, 现在来学习总结一下JSP.


1. JSP简介

JSP全称Java Server Pages, 是一种动态网页开发技术. JSP与Servlet是一体两面的, 因为JSP网页最终会被容器转译为Servlet源代码, 然后自动编译为.class文件, 再载入.class文件, 最后生成Servlet对象.

下面我们以一个Hello World的例子, 来分析以下JSP和Servlet的关系, 以及JSP的生命周期.

例: 用JSP输出Hello Word, 并分析转译的Servlet代码.

JSP代码如下:

<html>    <head>        <title>Hello JSP</title>    </head>    <boay>        <h1>Hello World!</h1>    </body></html>

这就是最简单地JSP的一段代码, 那么, 我们看看它转译成Servlet将会变成什么样子. 转译后的Servlet代码如下(将会略去部分代码, 只保留部分代码):

pubilc final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase    implements org.apache.jasper.runtime.JspSourseDependent{    //略...    public void _jspInit(){        //略...    }    public void _jspDestroy(){        //略...    }    public void _jspService(HttpServletRequest request, HttpServletResponse response)     throws java.io.IOException, ServletException{        //以下开始为JSP里面的隐式对象        PageContext pageContext = null;        HttpSession session = null;        ServletContext application = null;        ServletConfig config = null;        JspWriter out = null;        Object page = this;        //以上为JSP里面的隐式对象        JspWriter _jspx_out = null;        PageContext _jspx_page_context = null;        try{            //略...            out.write("<html>\n");            out.write("<head>\n");            out.write("<title>Hello JSP</title>\n");            out.write("</head>\n");            out.write("<body>\n");            out.write("<h1>Hello World!</h1>\n");            out.write("</body>\n");            out.write("</html>\n");        }catch(Throwable t){            //略...        }finally{            //略...        }    }}

JSP的生命周期

通过上面转译后的Servlet代码可以看到主要有三个重要的方法:_jspInit(), _jspDestroy(), _jspService()这三个方法, 对比Servlet, 我们可以大概猜到这三个方法分别是请求来临时的初始化操作, 请求来临时的善后操作, 请求来临时的处理操作.

那么, 这三个方法时从哪里来的呢? 如果我们想对请求来临的初始化/处理/善后想进行特别的处理是否应该重定义这三个方法?

在上述转译后的Servlet代码中, 我们可以看到, 该转译后的Servlet继承了org.apache.jasper.runtime.HttpJspBase类, 那么我们来大致查看一下HttpJspBase类中都有哪些方法, 他们的关系有时如何, HttpJspBase类代码如下:

public abstract class HttpJspBase extends HttpServlet implements HttpJspPage{//HttpJspBase是一个抽象类,说明该类的所有方法都应该由其子类来实现.    public final void init(ServletConfig config) throws ServletException{        super.init(config);        jspInit();        _jspInit();    }    //略...    public final void destroy(){        jspDestroy();        _jspDestroy();    }    public final void service(HttpServletRequest request, HttpServletResponse response)        throws ServletException, IOException{        _jspService(request, response);    }    public void jspInit(){}    public void _jspInit(){}    public void jspDestroy(){}    public void _jspDestroy(){}    public abstract void _jspService(HttpServletRequest request, HttpServletResponse response)        throws ServletException, IOException;}

通过上述代码可以看出Servlet的init()/destroy()/service()里面都调用了哪些方法.

  • init(): 其中调用了jspInit()和_jspInit().

    • _jspInit()是由转译后的Servlet进行自动重定义.
    • 如果想自己设置初始化的操作, 可以重定义jspInit().
  • destroy(): 其中调用了jspDestroy()和_jspDestroy().

    • _jspDestroy()是由转译后的Servlet进行自动重定义.
    • 如果想自己设置善后的操作, 可以重定义jspDestroy().
  • service(): 其中调用了_jspService(), JSP转译为Servlet后, 其中所定义的核心代码都在_jspService()中.

2. Servlet到JSP的转换

例: 将下面的Servlet代码转换为JSP代码
Servlet代码如下:

@WebServlet("/hello.view")public class FirstServlet extends HttpServlet{    @Override      protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=UTF-8");         PrintWriter out = response.getWriter();         String name = request.getParameter("name");        out.println("<html>");        out.println("<head>");        out.println("<title>hello Servlet</title>");        out.println("<head>");        out.println("<body>");        out.println("<h1> hello!" + name + "!</h1>");        out.println("</body>");        out.println("</html>");        out.close();    }}

转译成JSP代码如下:

<%@page contentType = "text/html" pageEncoding = "UTF-8"%><html>    <head>        <title>hello servlet</title>    </head>    <body>        <%            String name = request.getParameter("name");        %>        <h1>hello! <%= name%></h1>    </body></html>

JSP代码格式总结

  • JSP的代码格式与HTML基本类似. 如等这些标签都遵循和HTML一样的格式.
  • JSP中穿插Java代码: 写在<%%>中, 如下:
    • <% String name = request.getParameter(“name”); %>
  • JSP中穿插赋值语句: 写在<%=%>中, 如下:
    • <h1> hello!” + name + “!</h1> 转化为JSP代码为:<h1> hello! <%= name%></h1>
  • JSP中指示元素的格式: <%@指示元素 [属性=”值”]* %>, 如下:
    • <%@page contentType = “text/html” pageEncoding = “UTF-8” %>
  • 类成员或方法的声明: 写在<%!%>中, 具体示例使用方法后面会详细谈到.

3. 指示元素

什么是指示元素?
指示元素是在容器将JSP转译成Servlet代码的时候, 声明的一些必须遵守的信息. 在JSP中, 主要由三种常用的指示类型: page, include, taglib.

  • page: 告知容器如何转译目前的JSP网页.
  • include: 告知容器将别的JSP包含进来转译.
  • taglib: 告知容器如何转译这个页面的标签库(后面会谈到).

page指示类型

page指示类型使用示例:

<%@page import = "java.util.Date" %><%@page contentType = "text/html pageEncoding = UTF-8" %>...

上述代码中的import/contentType/pageEncoding都是page指示元素的属性.

page指示元素的属性

  • import: 告知容器在转译JSP时, 必须在源代码包括的import陈述, 比如需要用到的Java的包等.
  • contentType: 告知容器在转译JSP时, 使用的HttpServletRequest的setContentType(), 属性值即为setContentType()方法的属性值.
  • pageEncoding: 告知容器这个JSP网页文字的编码, 以及内容类型附加的charset设置.
  • 还有一些不常用的属性在此暂不列出.

include指示类型

include指示类型使用示例:

假设有如下代码: includeDemo.jsp

<%@ page contentType="text/html" pageEncoding="UTF-8" language="java" %><%@include file="header.jspf"%>    <h1>include 示范主体</h1><%@include file="foot.jspf" %>

header.jspf代码如下(.jspf文件是被.jsp文件include的文件, 本质上就是.jsp文件):

<html>    <head>        <%@page pageEncoding="UTF-8" %>        <title>include 示范开头</title>    </head>    <body>

foot.jspf代码如下:

<%@page pageEncoding="UTF-8" %>    </body></html>

在上述includeDemo.jsp进行转译时, 会将header.jspf和foot.jspf包含进来进行转译, 也就是说将<%@include file = “header.jspf” %>和<%@include file = “foot.jspf” %>分别用header.jspf和foot.jspf文件进行替换.

include指示元素包含进来的JSP们, 最终只会转译生成一个Servlet文件, 而后面提到的的网页则会生成一个个独立的Servlet.

4. 声明元素 Scriptlet元素 表达式元素 注释元素

声明元素

声明元素的语法为: <%! 类成员声明或方法声明%>, 示例如下:

<%!    String name = "dela";    String passwd = "123456";    boolean checkUser(String name, String passwd){        return this.name.equals(name) && this.passwd.equals(passwd);    }%>

上述代码转译后在Servlet中会生成如下代码:

pubilc final class index_jsp extends org.apache.jasper.runtime.HttpJspBase    implements org.apache.jasper.runtime.JspSourseDependent{    String name = "dela";    String passwd = "123456";    boolean checkUser(String name, String passwd){        return this.name.equals(name) && this.passwd.equals(passwd);    }    //略...}

你可能会想, 这样声明和直接写Java代码(即后面提到的Scriptlet元素)有什么区别, 不都是转译到Servlet中了吗?
当然不是, 声明元素中所写的Java代码将会生成HttpJspBase类中像init()/destroy()/service()这样的方法成员或数据成员. 而直接写的Java代码, 都将转译到_jspService()方法中.
声明元素的作用之一就是前面提到的: 我们想自定义JSP的一些初始和结尾工作时, 可以在声明元素中重定义jspInit()和jspDestroy()方法.

Scriptlet元素

Scriptlet元素就是前面提到的直接在JSP中编写Java代码, 格式为: <% Java语句 %>. 其示例前面都有提到过, 在此不过多赘述.

表达式元素

表达式元素就是前面提到的赋值语句, 格式为<%=Java表达式 %>.其示例前面也都有提到过, 在此不过多赘述.

注释元素

注释元素就是在JSP中的注释, 格式为:< !– 注释 – > .

5. 隐式对象

简单的讲, 就是将Servlet里面一些常用的对象设置为JSP里面的隐式对象. 比如, JSP中的out就是Servlet里面的PrintWriter对象, request就是HttpServletRequest对象. 隐式对象的存在就是为了简化Java代码, 我们不必要再通过getxxxx()来取得这些常用的对象.

JSP隐式对象的说明如下:
- out: 转译后对应JspWriter对象, 其内部关联一个PrintWriter对象.
- request: 转译后对应HttpServletRequest对象.
- response: 转译后对应HttpServletResponse对象.
- config: 转译后对应ServletConfig对象.
- application: 转译后对应ServletContext对象.
- session: 转译后对应HttpSession对象.
- pageContext: 转译后对应pageContext对象, 它提供了JSP页面资源的封装, 并可设置页面范围属性.
- exception: 转译后对应Throwable对象, 代表由其他JSP页面抛出的异常对象, 只会出现于JSP错误页面(isErrorPage属性设置为true的JSP页面).
- page: 转译后对应this.

需要注意的是: 隐式对象只能在<%%>与<%=%>之间使用, 因为隐式对象为_jspService()里面的局部变量, 无法在其他成员方法中使用.

6. 错误处理

在JSP中, 可用page指示元素的errorPage属性来指定错误处理页面来进行错误处理. 如下:

<%@page errorPage = "error.jsp" %>

然后在error.jsp中将page元素的isError属性设置为true. 随后在error.jsp中可通过打印隐式对象exception的错误信息(如异常堆栈信息), 以便后续处理.

原创粉丝点击