首页 > 代码库 > 一步一步学JSP(一)

一步一步学JSP(一)

1、JSP概述


         1.1为什么要使用JSP

       由于在Servlet中嵌入html代码非常麻烦,这常常使得Servlet很庞大,不便于页面的修改,难以维护,这样也就无法用网页设计工具来进行编辑了,页面的设计变得很麻烦,所以sun公司推出了JSP。JSP可以在html中嵌入java代码,可以在jsp页面中像在html页面一样写html代码,这样就不像在servlet中写html代码那样痛苦了,代码的可读性也变高了。

          1.2  什么是JSP

          JSP(Java Server Pages)是以Java语言为基础的动态网页开发技术,JSP与Java Servlet一样,是在服务器端执行的,不同的是先由服务器编译部署成Servlet执行。更多信息请查看JSP维基百科

2、JSP运行原理

   JSP的运行原理图如下:

技术分享

        JSP的执行过程:

  • 客户端发送请求
  • JSP Container 将JSP 翻译成Servlet 的源代码;
  • 将产生的Servlet 的源代码经过编译后,加载到内存执行;
  • 把结果Response (响应)发送至客户端。

         JSP和Servlet的执行效率相差不大,只是第一次执行JSP页面时需要进行编译。一般人都会以为JSP 的执行性能会和Servlet 相差很多,其实执行性能上的差别只在第一次的执行。因为JSP 在执行第一次后,会被编译成Servlet 的类文件,即为XXX.class,当再重复调用执行时,就直接执行第一次所产生的Servlet,而不用再重新把JSP编译成Servlet。因此,除了第一次的编译会花较久的时间之外,之后JSP 和Servlet 的执行速度就几乎相同了。在执行JSP 网页时,通常可分为两个时期:转译时期(Translation Time)和请求时期(Request  Time) 。

       tomcat为什么能处理jsp文件,因为在${tomcat}/conf/web.xml(这个文件存放这web应用的默认配置)文件中存在这样的配置:

    <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的,可以试验下,假如在自己的web.xml文件中配置一个servlet,该servlet处理所有的*.jsp请求,当你在访问相应的jsp时,始终都会走这个servlet

     我们先来写一个简单的jsp,里面写的东西不要求理解:

<%@page import="java.util.Date"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>JSP小例子</title>
  </head>
  
  <body>
     <%
     	Date date = new Date();
     %>
     今天是<%=date%>
  </body>
</html>
这个页面只是简单的输出了下当前的时间,产生的servlet存放在%tomcat%\work\引擎\主机\项目名\org\apache\jsp,生成的java源代码如下:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.Date;

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

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

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

    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 {
      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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <title>JSP小例子</title>\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("     ");

     	Date date = new Date();
     
      out.write("\r\n");
      out.write("     今天是");
      out.print(date);
      out.write("\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof 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 log(t.getMessage(), t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

从上面的代码不难开出与jsp生命周期相关的方法为:

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

demo_jsp的继承关系如下图

:技术分享

从上图不难看出jsp通过tomcat的jsp引擎处理后,实际上还是一个servlet,只不过我们访问jsp文件时,jsp引擎已经帮我们做好处理了。好,我们已经对jsp有所了解了,那么jsp页面是由什么组成的呢?

  • JSP原始代码中包含:JSP元素、Template(模板)dataJSP元素指将由JSP引擎直接处理的部分,这一部分必须符合JSP语法,否则会导致编译错误Template Data指的是JSP引擎不处理的部分。即标记在<%...%>以外的部分,例如:代码中的HTML内容等,这些数据会直接传送到客户端的浏览器
  • JSP组成
                 *     静态网页代码HTML

                 *     动态的Java代码(必须包含在特定的标签中)

3、jsp基本语法

        3.1、jsp指令元素

                           jsp指令元素的功能:

  • 用于指示JSP执行某些步骤,用于指示JSP表现特定行为  。 
  • 用来设定JSP网页的整体配置信息。

总的来说指令就是在页面提供一些配置信息的。语法的基本格式:<%@  directive [attribute="value"]*%>  ,jsp指令元素主要分为page指令,include指令,taglib指令。jsp指令不会向客户端产生任何输出,所有的指令元素在整个jsp文件都有效,为编译阶段提供全局的信息,理论上指令可以得到页面的任何位置 。

3.1.1 page指令

                  page指令的基本格式为<%@ page  [attribute="value"] *%>  ,用来定义jsp文件的全局属性,无论page指令出现在jsp文件的什么地方,它的作用都是整个jsp页面,为了保持持续的可读性和遵循良好的编程习惯,page指令最好存放在jsp文件的开头。这些属性可以单独使用也可以几个或多个同时使用,在jsp页面中只有import属性可以出现多次,其他属性只能出现一次(当然这些属性多次出现,而且都是相同的值都是可以的)。

属性配置:

        language:确定当前jsp所使用的语言,默认是java,为以后扩展用。

        pageEncoding:配置当前页面所保存的页面信息的编码

        contentType:定义jsp响应的MIME类型,例如:text/html; charset=UTF-8

             与pageEncoding的比较:

                       仅有pageEncoding: 配置当前页面的编码,配置jsp响应的MIME类型

                       仅有contentType: 配置当前页面的编码,配置jsp响应的MIME类型

                        两者都有:pageEncoding仅设置当前页面的编码,contentType设置jsp响应的MIME类型

            一般只需要配置pageEncoding就行了。

    import:导入当前jsp页面需要使用的包或类的列表,可以重复引用,多个之间用逗号分隔,导包的最后一    条可以输入多个分号,例如import="java.util.*"

     info:确定当前页面的输出信息

     session:确定当前页面是否可以使用session,默认为true

      extends: 确实jsp页面生成servlet,继承的父类,例如extends="java.util.List"

     errorPage: 确实当前页面出现异常时,跳转的页面

     isErrorPage: 是否为错误页面。如果设置成true,则可以使用exception内置对象(后面会介绍)

    isThreadSafe:默认为true,如果设置成false则会实现SingleThreadModel接口(这个接口以及废弃)

    isELIgnored:是否忽略el表达式,默认为false

    buffer: 当前servlet的缓冲区的大小,默认为8kb

   autoFlush:   是否自动刷新,当buffer缓存区被填写满后,会自动的刷新内容到浏览器

3.1.2 include指令

include指令的基本格式为<%@ include file="filename"%> ,include指令的作用是在jsp文件静态包含一个文件,同时由jsp解析包含的文件内容。静态包含的含义:用于通知JSP引擎在翻译当前JSP页面时将其他文件中的内容合并进当前JSP页面转换成的Servlet源文件中。当前JSP页面与静态引入的页面紧密结合为一个Servlet。

include指令注意事项:

  • file不能为一变量

          <% String url="index.html" ; %>
          <%@ include file = "<%= url %>" %>

  • 不可以在file 所指定的文件后接任何参数

        <%@ include file = "jw.jsp?nm=browser" %>

  •   被引入的文件必须遵循JSP语法,JSP引擎会按照处理JSP页面的方式处理里面的内容
  •   被引入的文件可以使用任意的扩展名,为了见名知意,JSP规范建议使用*.jspf(JSP fragments)作为静态引入文件的扩展名
  •    在将JSP文件翻译成servlet源文件时,JSP引擎将合并被引入的文件与当前JSP页面中的指令元素。除了import和pageEncoding属性之外,page指令的其他属性不能在这两个页面中有不同的设置值          

       使用include可以便于网站的维护,例如网站的头和尾的相关信息一般都是不变的,网站的实际内容是变得的,这样就可以使用include指令将头和尾的信息包含进来,专业当要修改头和尾时,只需要在对应的文件中进行修改,而不必修改其他的文件。例如<%@ include file="top.jsp"%> 实际的内容<%@ include file="foot.jsp"%> 

3.1.3 taglib指令

           taglib指令用于在jsp文件中导入标签库,常用的属性有uri: 标签文件的uri地址,prefix:标签组的命名空间前缀,关于标签库的详细内容将会在后续介绍。

4 jsp脚本元素

技术分享

4.1 声明标签(Declaration)

      声明的格式: <%! 声明1;[声明2];……%>,用于成员变量和方法的声明。声明的变量是全局变量,声明的方法将转换成servlet的方法,声明的作用范围是整个JSP页面,同时它只在一个JSP页面有效。例如:

    <%!
    	private String msg = "msg";
    	private void sayHi(String name){
    		System.out.println("Hi," + name);
   		}
    %>

4.2  代码块(Scriptlets)

        语法格式:<%  java code  %>,在“<%”和”%>”之间插入java程序片段,一个JSP页面可以有许多程序片段,这些代码块将被JSP服务器按照顺序执行,在一个代码块中声明的变量是JSP页面的局部变量,只在当前页面有效,代码块中不能定义方法,代码块在JSP编译后,将成为对应的Servlet的_jspService()方法体的一部分例如

   <%
     	Date date = new Date();
     	System.out.println("当前时间:" + date);
     %>

4.3 表达式(Expression)

        语法格式:<%= 变量或表达式 %>,表达式的计算结果转换成字符串,使用隐含对象out进行输出,结果显示在页面中标签所在的位置例如:<%=“abc” %> 等价于 out.print(“abc”);,JSP脚本表达式中的变量或表达式后面不能有分号(;)

     练习一:输入h1-h6

   

<%@page import="java.util.Date"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>输出h1-h6</title>
  </head>
  <body>
    <%
    	for(int i = 1; i <=6; i++){
    %>
    	<h<%=i%>>Hello World!</h<%=i%>>
    <%		
    	}
    %>
  </body>
</html>

从上面的练习可以看出代码块是可以分散使用的,只要保证<%和%>成对出现就行。


练习二:输出当前的日期,格式为(xxxx年xx月xx日 星期x)

<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.text.DateFormat"%>
<%@page import="java.util.Date"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>当前日期</title>
  </head>
  <body>
    <%
    	Date curDate = new Date();
    	DateFormat df = new SimpleDateFormat("yyyy年MM月dd日 E");
    %>
    <p><%=df.format(curDate)%></p>
  </body>
</html>

练习三:输出九九乘法表(仅能使用jsp脚本)

http://blog.csdn.net/ricciozhang/article/details/43197613

5、 jsp页面注释

  •      jsp注释:<%-- 注释内容--%>,转换阶段消失,只能被开发人员看到,属于源码级别的注释
  •      html注释: <!--注释内容-->,在转换阶段不会消失,在页面中也能看到
  •     java注释://、/*注释内容*/、/**注释内容*/,转换阶段不会消失,在编译时消失

例如:

    <%--jsp注释--%>
    <!-- html注释 -->
    <%
    	//java行级注释
    	/*
    		java块级注释
    	*/
    	/**
    	*  javaDoc
    	*/
    %>

6、jsp内置对象

         jsp的9大内置对象如下

技术分享

jsp内置对象的分类:

技术分享

为什么在jsp中能直接的使用这些对象(exception对象需要设置isErrorPage="true",才能使用)?因为在jsp转换成servlet是在_jspService()方法中定义了这些变量,所以能使用。

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

    PageContext pageContext = null;
    HttpSession session = null;
    Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);
    if (exception != null) {
      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;

由上可以很清楚的看出内置对象的类型:

  • request        HttpServletRequest
  • response        HttpServletResponse
  • session        HttpSession
  • application               ServletContext
  • config        ServletConfig
  • page        this
  • pageContext    PageContext
  • exception               Throwable
  • out                   JspWriter     

page对象:

    page对象代表了正在运行的由jsp产生的类对象。这个对象其实并没有太大的用处,一般不建议使用该对象。page对象指的是当前jsp程序本身的对象,有点像类中的this,page对象其实是java.lang.Object类的实例对象。

out对象:

       向客户端输出数据,管理服务器输出缓冲区内部使用PrintWriter对象来输出文本级数据,通过page指令的buffer属性来调整缓冲区的大小,默认的缓冲区是8kb

技术分享

注意:在jsp页面不能在调用response.getOutputStream(),否则会抛出异常。

out对象的工作原理如下:

技术分享


config对象:

       用来取得jsp的初始化参数信息,需要在WEB-INF/web.xml中进行配置,jsp文件也可以作为servlet配置,例如在web.xml中的进行如下的配置:

	<servlet>
		<servlet-name>demo</servlet-name>
		<jsp-file>/demo.jsp</jsp-file>
		<init-param>
			<param-name>name</param-name>
			<param-value>Riccio Zhang</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>demo</servlet-name>
		<url-pattern>/jsp/demo/</url-pattern>
    </servlet-mapping>	

那么就可以再demo.jsp文件中取得配置的参数:

    <%
    	String name = config.getInitParameter("name");
    	System.out.println(name);
    %>
注意:只有通过web.xml文件中配置的路径访问在能获取到参数信息,否则是获取不到参数的。使用jsp文件访问使用的是tomcat的servlet引擎,并不知道配置的相关参数信息,只有通过自定义的路径才能获取到参数。

response对象:服务器对浏览器的响应

request对象:浏览器向服务器发出的请求作用范围是一次请求(可能涉及多个jsp或servlet)

exception对象:exception对象是java.lang.Trowable类的实例,exception对象用来处理JSP文件在执行时所有发生的错误和异常。exception对象可以和page指令一起使 用,通过指定某一个页面为错误处理页面,对错误进行处理<%@ page isErrorPage=”true “%>的页面内使用。

application对象:作用范围:整个web项目

session对象:作用范围:一个会话

pageContext对象:pageContext对象可以直译为“页面上下文”对象,代表的是当前页面运行的一些属性。它是javax.servlet.jsp.PageContext类的实例对象,可以使用PageContext类的方法,PageContext对象继承自javax.servlet.jsp.JspContext。pageContext对象提供了对JSP页面所有的对象及命名空间的访问。提供了page范围的存取数据的方法:Object getAttribute(String name),void removeAttribute(String name),void setAttribute(String name, Object value)

            

  <%
    	pageContext.setAttribute("name", "Riccio Zhang");
        String name = (String)pageContext.getAttribute("name");
        System.out.println(name);
        pageContext.removeAttribute("name"); //等价于pageContext.setAttribute("name", null),为了增强可读性还是使用removeAttribute方法
        System.out.println(name);;;;;
    %>
           jsp的四种数据范围:

  •                   page:当前jsp页面
  •                   request:一次请求
  •                   session:一个会话
  •                   application:整个web项目
     pageContext对象封装着对其他8个内置对象的引用,可以通过相应的get方法来获取引用,为什么要封装这8个对象呢?通过封装这8个内置的对象,可以方便编程,你只需要把pageContext给我传进来,其它对象就都可以用了,而不需要把一个个零散的对象都给传进来,这也为后面将会将到的EL表达式提供了方便,这里再次体现了封装的思想。

      pageContext除了能在page域存取数据外,还能提供了在其它域存取数据的方法:

  • public java.lang.Object getAttribute(java.lang.String name,int scope),
  •  public void setAttribute(java.lang.String name, java.lang.Object value,int scope)
  •  public void removeAttribute(java.lang.String name,int scope)

代表各个域的常量:

  •  PageContext.APPLICATION_SCOPE
  • PageContext.SESSION_SCOPE
  • PageContext.REQUEST_SCOPE
  • PageContext.PAGE_SCOPE


    <%
        //在各个域中存储数据
        pageContext.setAttribute("name", "name_page", PageContext.PAGE_SCOPE); //与pageContext.setAttribute("name", "name_page");等价
        pageContext.setAttribute("name", "name_request", PageContext.REQUEST_SCOPE);
        pageContext.setAttribute("name", "name_session", PageContext.SESSION_SCOPE);
        pageContext.setAttribute("name", "name_application", PageContext.APPLICATION_SCOPE);
        
        //在各个域中取出数据,并打印到控制台上
        String name_page = (String)pageContext.getAttribute("name", PageContext.PAGE_SCOPE);//与pageContext.getAttribute("name");等价
        System.out.println("PAGE_SCOPE name = " + name_page);
        
        String name_request = (String)pageContext.getAttribute("name", PageContext.REQUEST_SCOPE);
        System.out.println("REQUEST_SCOPE name = " + name_request);
        
        String name_session = (String)pageContext.getAttribute("name", PageContext.SESSION_SCOPE);
        System.out.println("SESSION_SCOPE name = " + name_session);
        String name_application = (String)pageContext.getAttribute("name", PageContext.APPLICATION_SCOPE);
        System.out.println("APPLICATION_SCOPE name = " + name_application);
  
    %>

最后比较重要的一个方法就是findAttribute方法,先来看看这个方法实现的源代码:

    public Object findAttribute(final String name) {
        if (SecurityUtil.isPackageProtectionEnabled()) {
            return AccessController.doPrivileged(new PrivilegedAction() { //HTTPS使用
                public Object run() {
                    if (name == null) {
                        throw new NullPointerException(Localizer
                                .getMessage("jsp.error.attribute.null_name"));
                    }

                    return doFindAttribute(name);
                }
            });
        } else { //一般的HTTP使用
            if (name == null) {
                throw new NullPointerException(Localizer
                        .getMessage("jsp.error.attribute.null_name"));
            }

            return doFindAttribute(name);
        }
    }

    private Object doFindAttribute(String name) {

        Object o = attributes.get(name);
        if (o != null)
            return o;

        o = request.getAttribute(name);
        if (o != null)
            return o;

        if (session != null) {
            try {
                o = session.getAttribute(name);
            } catch(IllegalStateException ise) {
                // Session has been invalidated.
                // Ignore and fall through to application scope.
            }
            if (o != null)
                return o;
        }

        return context.getAttribute(name);
    }

这个方法会从各个域中去取数据,如果取到了就直接返回,如果没有取到,则继续往下走,查找的顺序为:page --> request -->session --> application。这个方法再后续中也是很重要的一个方法。

    <%
    	//pageContext.setAttribute("user", "zq_page", PageContext.PAGE_SCOPE);
	  pageContext.setAttribute("user", "zq_request", PageContext.REQUEST_SCOPE);
	  pageContext.setAttribute("user", "zq_session", PageContext.SESSION_SCOPE);
	  pageContext.setAttribute("user", "zq_application", PageContext.APPLICATION_SCOPE);
		
	  String findedUser = (String)pageContext.findAttribute("user");
	  System.out.println(findedUser);
    %>
可以注释掉相应的域的存值语句去验证上面的顺序。

练习:完成猜数游戏

<%@page import="java.util.Random"%>
<%@ page language="java"  pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>猜数游戏</title>
  </head>
  <body>
    <%
    	//从session中获取那个随机的数字
    	Integer randNum = (Integer)session.getAttribute("randNum");
    	
    	//产生一个随机的数字
    	if(randNum == null){
    		Random rand = new Random();
    		randNum = rand.nextInt(100) + 1;
    		session.setAttribute("randNum", randNum);
    	}
    %>
    <p>
    	<%
    		String num = request.getParameter("num");
    		if(num != null && !num.equals("")){
    			int n = Integer.valueOf(num);
    			if( n == randNum ){
    				session.removeAttribute("randNum");
    				out.print("恭喜您,猜对了!");
    			}else if(n > randNum){
    				out.print("对不起,您猜错大了!");
    			}else{
    				out.print("对不起,您猜错小了!");
    			}
    		}
    	%>
    </p>
    <form action="" method="post">
    	请输入一个1~100之间的整数:<input type="text" name="num"><br/>
    	<input type="submit" value=http://www.mamicode.com/"猜"/>>

7、JSP标签

         JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。
jsp常用标签:

<jsp:useBean> 在指定范围内获取需要的javabean对象,如果不存在则创建

  • id,指定范围内,当前bean的实例化对象的变量名
  • scope,当前bean的使用,范围取值:"page | request | session | application",默认为page
  • class ,获得指定bean的实例对象,如果没有则创建取值:指定bean的完整路径名
  • type ,获得指定bean的实例对象,如果没有则抛异常,取值:指定bean的完整路径名
  • beanName,使用java.beans.Beans实例化bean对象,取值:指定bean的完整路径名
    
package cn.zq.domain;

public class User {
	private String name;
	private int age;
	private String address;
	
	public User() {}
	
	public User(String name, int age, String address) {
		this.name = name;
		this.age = age;
		this.address = address;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", address=" + address
				+ "]";
	}
	
}

 <%
    	User u = new User("Riccio Zhang", 21, "广州市");
    	pageContext.setAttribute("user", u);
    %>
    
    <%--
    	这里可以从指定域中获取到User对象
     --%>
    <jsp:useBean id="user" class="cn.zq.domain.User" scope="page"/>
	<%=user%>
	
	<%--
		此处会自动的创建一个变量名为user2的javabean,并存放到指定域中
	 --%>
    <jsp:useBean id="user2" class="cn.zq.domain.User"/>
    <%=user2%>
    
    <%--
    	此处会抛出异常,用type指定的javabean的完整名称时,未获取到会抛出异常
	    <jsp:useBean id="user3" type="cn.zq.domain.User"/>
     --%>
     
     <%--
     	未获取到指定javabean,则会调用 java.beans.Beans.instantiate会实例化指定的bean,
     	使用beanName属性时,不能使用class属性,只能使用type属性
      --%>
     <jsp:useBean id="user4" beanName="cn.zq.domain.User" type="cn.zq.domain.User" />
     <%=user4 %>

<jsp:setProperty >使用Bean的setter方法给bean的属性设置值。在使用之前必须使用<jsp:useBean>声明一个bean

  • name,使用已有的bean,取值必须与<jsp:useBean>的id匹配,如果不存在抛异常
  • property,bean的属性值
  •  value ,需要设置的值
  • param ,请求参数的值,取值必须与URL参数的值相同,如果没有此参数则不赋值

注意:value与param不能同时使用


     <jsp:useBean id="user" class="cn.zq.domain.User"/>
     <jsp:setProperty  name="user" property="name"  value=http://www.mamicode.com/"Riccio Zhang"/>>
<jsp:getProperty>使用bean的getter方法获得属性的值,在使用之前必须使用<jsp:useBean>声明一个bean

  • name,需要获得bean的实例对象变量值,取值必须与<jsp:useBean>的id匹配
  • property,需要获得bean的属性值
     <jsp:useBean id="user" class="cn.zq.domain.User"/>
     <jsp:setProperty  name="user" property="name"  value=http://www.mamicode.com/"Riccio Zhang"/>>

<jsp:include>

  • 语法

<jsp:include page={"relativeURL" | "<%= expression %>"} />

                   或
                  <jsp:include page={"relativeURL" | "<%= expression %>"} >
                          <jsp:param name="PN" value=http://www.mamicode.com/"{PV | }" /> *
                 </jsp:include> 

                     另一个属性flush:表示在动态包含另一个文件时,是否先刷新

  • 用于把另一个资源的输出内容插入进当前JSP页面的输出内容中,这种在JSP页面执行时的引入方式称之为动态引入

org.apache.jasper.runtime.JspRuntimeLibrary

 public static void include(ServletRequest request,
                               ServletResponse response,
                               String relativePath,
                               JspWriter out,
                               boolean flush)
        throws IOException, ServletException {

        if (flush && !(out instanceof BodyContent))
            out.flush();
        String resourcePath = getContextRelativePath(request, relativePath);
        RequestDispatcher rd = request.getRequestDispatcher(resourcePath);

        rd.include(request,
                   new ServletResponseWrapperInclude(response, out));

    }


<jsp:include>和include指令的比较:

  • 使用<jsp:include>标签和include指令都可以把一个页面的内容分成多个组件来生成,开发者不必再把页眉和页脚部分的相同的HTML代码复制到每个JSP文件中,从而可以更轻松的完成维护工作,但是合并过程需要遵循HTML语法结构。例如:<html><head><body>个数等
  • <jsp:include>标签是在当前JSP页面的执行期间引入被引入资源的输出内容。当前JSP页面与被动态引入的资源是两个彼此独立的执行实体,被动态引入的资源必须是一个能够独立被web容器调用和执行的资源。include指令只能引入遵循JSP格式的文件,被引入文件与当前JSP文件共同被编译成一个servlet的源文件
  • <jsp:include>标签对JSP引擎编译JSP页面的过程不起作用,它是在JSP页面的执行期间才被调用,因此不会影响两个页面的编译。由于include指令是在JSP引擎编译JSP页面的过程中被编译处理的,所以它对JSP引擎编译JSP页面的过程起作用。如果多个JSP页面中都要用到一些相同的声明,那么就可以把这些声明语句放在一个单独的文件中编写,然后在每个JSP页面中使用include指令将那个文件包含进来

通过上面的比较不难得出在开发时,尽量的用include指令来代替<jsp:include>,<jsp:include>会增加服务器的负担。


demo.jsp

     <jsp:include page="include.jsp">
     	<jsp:param name="country" value=http://www.mamicode.com/"中国"/>>

include.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<p>
	获取带的参数为:<%=request.getParameter("country")%>
</p>

发现在include.jsp中获取的是乱码,为什么是乱码呢?仔细查看如下的源代码:

  org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "include.jsp" + (("include.jsp").indexOf(‘?‘)>0? ‘&‘: ‘?‘) + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("country", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("中国", request.getCharacterEncoding()), out, false);

这个参数传递参数时先通过编码,编码是通过request.getCharacterEncoding()获取的,而我们并没有设置相应的值,只需要在包含语句之前加上这行java代码乱码就解决了

request.setCharacterEncoding("UTF-8");


<jsp:forward>将请求传递给另一个JSP页面。

  • <jsp:forward page={"relativeURL" | "<%= expression %>"} />

          或
        <jsp:forward page={"relativeURL" | "<%= expression %>"} >
                 <jsp:param name="PN" value=http://www.mamicode.com/"{PV | "}/> *
       </jsp:forward>

注意:被forward转发的资源必须与发送请求的页面处于相同的上下文环境中,每当遇到此标签时,容器就会停止执行当前的JSP,转而执行被转发的资源

     <jsp:forward page="forward.jsp" >
     	<jsp:param name="country" value=http://www.mamicode.com/"中国"/>>


练习:实现简单的计算器http://blog.csdn.net/ricciozhang/article/details/43233819


一步一步学JSP(一)