我学习JSP的一点体会

 我现在已经没有那么热衷java技术,我想现在有必要写一下我学习jsp的一些体
会,否则过一段时间可能我已经忘记jsp是啥玩意了,呵呵(当然,这里写的仅仅
一点点)。
    本文使用的环境是jdk1.5,Tomcat5.5版本。本文并不进行JSP与其他相关技术的
比较,不进行JSP在J2EE中扮演作用的讨论,只针对jsp技术的一些细节发表自己的
看法,期望起到抛砖引玉的作用。
    1.JSP运行原理
    当一个web容器接收到以.jsp为扩展名的URL的访问请求时,它将把该访问请求
交给JSP引擎去处理,JSP引擎负责解释和执行JSP页面。对Tomcat而言,这个JSP引
擎其实就是一个Servlet程序:org.apache.jasper.servlet.JspServlet,大家可以
在tomcat目录下面的conf/web.xml里找到这样一些内容:
    <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>
    ......
        <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
    </servlet-mapping>
    每个JSP页面在第一次被访问时,JSP引擎把这个jsp页面翻译成一个servlet源
程序,接着再把这个servlet源程序编译成servlet的class类文件,然后由web容器
(其实是里面的servlet引擎)像调用普通servlet程序一样的方式来装载和解释执行
这个由JSP页面的翻译成的servlet程序。(servlet源程序在tomcat目录下的work/
Catalina/localhost下面)。
    我的一个JSP文件index.jsp翻译成的servlet的源程序示例如下(所有jsp文件翻
译成的结构都基本如此)。
import javax.servlet.jsp.*;

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

  private static java.util.List _jspx_dependants;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse
response)
        throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html");
      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()语句
            ......
            ......
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          out.clearBuffer();
        if (_jspx_page_context != null)
_jspx_page_context.handlePageException(t);
      }
    } finally {
      if (_jspxFactory != null)
_jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}
    2.JSP的基本语法
    我就不具体列举了,因为这个大家随便翻一本讲jsp的书都有讲的。我主要讲一些
注意点。
    1)在jsp里如果使用java类,那么你的这些类都必须有包的定义。
    2)使用预定义的变量:request,response,out,session,application,config,
pageContext和page。注意这些变量是局部变量!大家可以看到jsp翻译成的servlet源
程序,这些变量都是定义在_jspService方法里的。所以如果你编写的代码翻译后不是
在_jspService方法里,那么你就不能使用这些变量。比如,由于JSP声明<%! Field or
Method Definition %>产生_jspService方法之外的代码,因此在声明中不能访问这些
变量。
    3)关于JSP指令像<% directive att="val"%>的形式。有page,include,taglib和
tag。关于JSP动作像<jsp:xxx>...</jsp:xxx>的形式,有jsp:include,jsp:useBean和
jsp:invoke。对于JSP指令中的include和JSP动作的jsp:include很容易让人混淆,我
看到一段英文文字说得比较清楚。
    If a file included with <%@ include %> changes, its changes will not be
noticed until the page containing the <%@ include %> directive also changes.
Recall from chapter 1 that the JSP engine notices when files are changed and
processes them automatically. However, the container doesn’t keep track of
which pages include <%@ include %> directives. When page A uses <%@
include %> to include page B, page B’s data is simply included in page A
every time it is compiled. Therefore, page A must be changed—and recompiled—
for any changes in B to take effect. By contrast, <jsp:include> notices
changes immediately.
    Because <%@ include %> works as if you had inserted the target file using a
text editor, it only works for basic text, JSP fragments, and so on. If your
application also has a Java servlet, you cannot include it with <%@ include %>.
Instead, you need to refer to it with <jsp:include>. ( Java servlets are an
advanced topic more for programmers than page designers; do not be concerned
if you have no experience with them.)
    The <%@ include %> directive is, in many cases, more efficient than
<jsp:include>, but it also uses much more disk space when large files are
included. Either way, the differences in efficiency between the two approaches
usually are not too important.
    With <jsp:include>, the two pages involved—call them page A and page
B—are two entirely separate pages. They can use the same names for different
variables, or they can use different prefixes for the same tag library.
With <%@ include %>, because page A and page B are essentially merged
before being compiled, there might be clashes between names within the
two pages.
    4)关于JSP动作<jsp:useBean>的说明,其实如果用了表达式语言或者structs的话,不

写很冗长的的类似的东西。
    3.关于预定义变量的out对象的说明
    JSP页面要真正的像客户端输出东西,要注意,可以把out对象有个一个缓冲区,翻译成

servlet程序由servelt引擎又给他提供一个缓冲区。out对象是pageContext.getOut()获得
的,
是一个JspWriter类型的对象。servlet的缓冲区内容写向客户端是用
ServletResponse.getWriter()
方法得到的PrintWriter对象的方法写入的。一版情况是jsp页面先写入out对象的缓冲区,
out
对象的缓冲区满了后又写入servlet的缓冲区,最后输出到客户端。当然了,out对象的缓冲

是可以通过page指令的buffer和autoflush两个属性进行设置的。buffer可以设置out对象缓
冲区
的有无,大小。当buffer设置不为none时,说明out对象有缓冲区,大小默认是8KB,此时如

autoFlush设置为true,则out缓冲区满了会自动刷新,写到servlet缓冲区里去。如果
autoFlush
设置为false,则out缓冲区满了会抛出IOException异常。如果buffer设置为none,那么说

out对象没有缓冲区,直接写入的是servlet的缓冲区。此时autoFlush只能设置为true。
比如一个简单的例子:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
buffer="none"%>
<html>
<head>
<title>Test</title>
</head>
<body>
<%
    out.println("one<br>");
    response.getWriter().println("two<br>");
%>
</body>
</html>
这个jsp页面输出的是
one
two
当把buffer不设置为none时,输出是
two
one
这个道理是很容易理解的。
接下来另一段内容:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="javax.servlet.ServletOutputStream" %>
<html>
<head>
<title>Test</title>
</head>
<body>
<%
    ServletOutputStream out2=response.getOutputStream();
    out2.println("test<br>");
%>
</body>
</html>
这个是会报错的,因为
<%
    ServletOutputStream out2=response.getOutputStream();
    out2.println("test<br>");
%>
这段代码前面的内容已经先调用out.write()了。只要调用了这个
out对象,最后会调用ServletResponse.getWriter()方法输出到
客户端的。这和ServletOutputStream out2=response.getOutputStream();
发生了冲突。大家看getOutputStream()的异常抛出说明就很清楚了:
java.lang.IllegalStateException - if the getWriter method has been
called on this response
java.io.IOException - if an input or output exception occurred
这个我深有体会啊,以前用jspSmartUpload做文件的上传下载时就出现
类似问题,原因找了一段时间才搞明白,当然了,现在我用apache的
commons-fileupload做文件上传下载发现更方便。哈哈。
    4.关于JSP使用java代码的策略
    从简单应用到复杂应用依次是(根据情况选择一个):
    1)直接调用Java代码。(代码直接写在jsp页面中)
    2)间接调用Java代码。(很多具体代码写在一个java类后jsp再调用)
    3)使用bean。
    4)使用MVC框架
    5)使用JSP表达式语言(一般和bean及MVC组合使用)。
    6)使用定制标签。

ps:我只是想到什么就写了一下什么,本来很多东西想写的,比如JSP标签具体
是怎么回事,JSP中乱码问题等,但是发现要写又要码很多字了。。。。 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值