您当前的位置:首页 > 计算机 > 编程开发 > Java

在HTML中插入JSP代码

时间:10-11来源:作者:点击数:

JSP 文件可以只包含 HTML,也可以插入 JSP 代码,客户端发起请求后,HTML和插入的 JSP 脚本都会被翻译成 Servlet 程序,然后再编译并运行。

小脚本格式(scriptlet)

小脚本格式是指可以在 <% 和 %> 之间插入 JSP 代码:

<%
    // JSP Code
%>

JSP代码可以包含任意的Java语句、变量、方法或表达式,只要它们是有效的。

你也可以使用类似 XML 的格式插入:

<jsp:scriptlet>
    // JSP Code
</jsp:scriptlet>

文本、HTML标签等都必须写在 JSP 的外边,例如:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>演示页面</title>
</head>
<body>
<p>
    1+2+3+...+99+100 =
    <%
        int result = 0;
        for(int i=1; i<=100; i++){
            result += i;
        }
        out.print(result);
    %>
</p>
</body>
</html>

将上面的代码保存到 demo.jsp 并放到站点根目录,假设你为当前虚拟主机分配了 www.jspdemo.com 域名,访问 www.jspdemo.com:8080/demo.jsp,就可以看到输出内容。


图1  演示页面

打开 $CATALINA_HOME\\work\Catalina\www.jspdemo.com\_\org\apache\jsp 目录,你会看到由 JSP 翻译生成的 Servlet 程序 demo_jsp.java,部分代码如下所示:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

// demo.jsp 页面的内容被转换为 demo_jsp 类
public final class demo_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

    public void _jspInit() {
        // 初始化
    }

    public void _jspDestroy() {
        // 销毁
    }

    // 处理 http 请求,生成 html 代码
    public void _jspService(final javax.servlet.http.HttpServletRequest request,
        final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

        out.write("<!DOCTYPE html>\r\n");
        out.write("<html lang=\"zh\">\r\n");
        out.write("<head>\r\n");
        out.write("    <meta charset=\"UTF-8\">\r\n");
        out.write("    <title>演示页面</title>\r\n");
        out.write("</head>\r\n");
        out.write("<body>\r\n");
        out.write("<p>\r\n");
        out.write("    1+2+3+...+99+100 = \r\n");
        out.write("    ");

        int result = 0;
        for(int i=1; i<=100; i++){
            result += i;
        }
        out.print(result);

        out.write("\r\n");
        out.write("</p>\r\n");
        out.write("</body>\r\n");
        out.write("</html>");
    }
}

可以很清楚的看到 JSP 页面翻译生成的 Java 代码,在<%与%>之间的代码都被放到了 _jspService() 方法内部,包括声明的变量,也是局部变量。

声明格式(declaration)

声明格式是指可以在 <%! 和 %> 之间声明变量、方法和类。与小脚本格式不同的是:

  • <% ... %> 声明的是局部变量,会被放到 _jspService() 方法内部。
  • <% .. %> 不能声明方法,因为Java规定方法不能嵌套声明。
  • <%! ... %> 之间声明的是成员变量,由多线程共享。

注意:<%! ... %> 只能用来声明变量、方法和类,不能包含表达式。

也可以使用类似 XML 的格式插入:

<jsp:declaration>
    // JSP Code
</jsp:declaration>

示例代码:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>演示页面</title>
</head>
<body>
<%!
    int click = 0;
%>
<p>
    1+2+3+...+99+100 =
    <%
        int result = 0;
        for(int i=1; i<=100; i++){
            result += i;
        }
        out.print(result);

        click++;
    %>
</p>
<p>你是第<%= click %>位访客</p>
</body>
</html>

生成的 demo_jsp.java 部分代码如下:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class demo_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {

    int click = 0;

    public void _jspInit() {
        // 初始化
    }

    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 {

        out.write("<!DOCTYPE html>\r\n");
        out.write("<html lang=\"zh\">\r\n");
        out.write("<head>\r\n");
        out.write("    <meta charset=\"UTF-8\">\r\n");
        out.write("    <title>演示页面</title>\r\n");
        out.write("</head>\r\n");
        out.write("<body>\r\n");
        out.write("\r\n");
        out.write("<p>\r\n");
        out.write("    1+2+3+...+99+100 = \r\n");
        out.write("    ");

        int result = 0;
        for(int i=1; i<=100; i++){
            result += i;
        }
        out.print(result);

        click++;

        out.write("\r\n");
        out.write("</p>\r\n");
        out.write("<p>你是第");
        out.print( click );
        out.write("位访客</p>\r\n");
        out.write("</body>\r\n");
        out.write("</html>");
    }
}

可以看到在 <%! 和 %> 之间声明的 click 变量被翻译成了一个成员变量,与在 <% 和 %> 之间声明的变量作用域不同,访问权限也不同,<%! 和 %> 之间声明的变量在整个 JSP 页面内都有效。

重复访问该页面,会发现每次访客数量都会增加。

这是因为 Servlet 是单实例多线程的,成员变量在堆区分配内存,并一直存在,由多个线程共享,直到服务器关闭或JSP文件更新。而方法内的局部变量在栈区分配内存,线程结束后将被回收。

也就是说,当多个用户请求一个JSP 页面时,JSP 容器会为每个用户启动一个线程,这些线程由JSP容器来管理,这些线程共享 JSP 页面的成员变量,因此任何一个用户对 JSP 页面成员变量操作的结果,都会影响到其他用户。

demo_jsp 类只会在首次访问时被实例化,以后一直存在,新用户访问页面会启动一个线程,并使用该实例的数据,所以每次刷新页面 click 变量都会加1。

Servlet 单实例多线程的特性提高了程序的执行效率,启动一个线程的代价很小,在高并发量方面有很大的优势。但是它也有副作用,带来了线程安全问题,一个线程对数据的操作会影响到下一个线程。所以我建议,除非有必要,否则不要再 <%! 和 %> 之间声明变量。

表达式格式(expression)

前面的JSP代码,输出IP地址时用到了 out.print() 语句:

<% out.println(request.getRemoteAddr()); %>

其实还有一种简写,更加方便:

<%= request.getRemoteAddr() %>

示例代码:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>演示页面</title>
</head>
<body>
    <p>
        你的IP地址是:
        <%= request.getRemoteAddr() %>
    </p>
</body>
</html>

也可以使用类似 XML 的格式:

<jsp:expression>
    // JSP Code
</jsp:expression>

<%= ... %> 可以认为是 out.print() 语句的简写,用来输出一个变量或表达式的值,注意结尾不能有分号(;)。

提示:<%= 是一个完整的界定符,中间不能有空格。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
上一篇:JSP生命周期 下一篇:JSP注释
推荐内容
相关内容
栏目更新
栏目热门