欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Servlet之JSP_03 JSTL/EL 表达式

程序员文章站 2022-04-23 13:14:47
...
准备工作:在JSP 中启用 EL 表达式
<%@ page isELIgnored="false"%>

一、什么是 JSTL/EL 
JSTL :  jsp 标准标签库(Jsp Standard Tag Library)
EL:  表达式语言 (Expression Language)

JSTL/EL 提供了一些通用的核心功能,如:设置变量的 scope,判断,迭代等。
使JSP开发者提高了开发效率。


二、 JSTL 与 EL 的区别和联系
EL 表达式最初只用于 JSTL 标签(或其它自定义标签)的属性中。
在后来的 JSP 定义版本中,允许 EL 单独在 JSP 中使用,用于简单属性的输出。

例如: ${user.id} 可以把 user 对象的 id 属性写入到 jsp 中。但这并不表明 JSTL 就没有用处了,JSTL 可以提供:条件判断,循环输出,html 标签过滤,URLs,日期格、数字式化等功能。


三、什么对象可以在 EL 表达式中使用?

      问题:
      在 jsp 页面中的 Java 代码块 <% %> 中定义的 java 对象,可以直接在 EL 表达式 中使用吗?

      回答:
      不可以。访问不到。

      EL 表达式 只会调用这四个对象(page, request, session, application)的 getAtrribute(string) 方法,来获取表达式中的对象。
      这就是所谓的 EL 内置 scope 对象 —— 它们分别对应四个 jsp 的内置对象。
      如果 page 对象中没有,则会到 request 对象寻找。依次向更大 scope 的对象中寻找。

      所以在 Java 代码块 <% %> 中新建类对象,需要使用上述 scope 对象的 setAttribute()  方法,将新建的对象绑定到 scope 对象中。才能被 EL 表达式 引用到。


      例子:
<%@ page language="java" contentType="text/html; charset=UTF-8" 
    pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page import="com.test.pojo.User" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
	
	<%
	/***********************************************
	    Pay Attention:
	 ===============================================
	   
		   When using EL or JSTL, the following
		   
	   			User user = new User();
	   		
	   	   will not work.
	   
	   ==============================================
	   
	*/	   	   
	   pageContext.setAttribute("user", new User());
	   	   
	   //request.setAttribute("user", new User());
	   
	%>

	
	<h4>Using EL</h4>
	<p>${user.name }</p>
	<p>${user.getName() }</p>

	<h4>Using JSTL</h4>
	<p><c:out value="${user.name}" /></p>
	<p><c:out value="${user.getName()}" /></p>


    
    <%
        String hello = "Hello World!";
    %>
	<h4>Using JSP Expression</h4>
    <p><%=hello%></p>
	
</body>
</html>


User.java
package com.test.pojo;
public class User {	
	private String name ="default";	
	public String getName(){
		return "Welcome to JSTL!";
	}
}



结果输出:
引用

Using EL
Welcome to JSTL!
Welcome to JSTL!

Using JSTL
Welcome to JSTL!
Welcome to JSTL!

Using JSP Expression
Hello World!



生成的 JSP 源码:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.78
 * Generated at: 2017-06-21 19:40:24 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import com.test.pojo.User;

public final class home_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<java.lang.String,java.lang.Long> _jspx_dependants;

  private org.apache.jasper.runtime.TagHandlerPool _005fjspx_005ftagPool_005fc_005fout_0026_005fvalue_005fnobody;

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
    _005fjspx_005ftagPool_005fc_005fout_0026_005fvalue_005fnobody = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());
  }

  public void _jspDestroy() {
    _005fjspx_005ftagPool_005fc_005fout_0026_005fvalue_005fnobody.release();
  }

  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("\n");
      out.write("  \n");
      out.write("  \n");
      out.write("<html>  \n");
      out.write("<head>  \n");
      out.write("\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
      out.write("\t<title>Hello World</title>  \n");
      out.write("</head>  \n");
      out.write("<body>  \n");
      out.write("      \n");
      out.write("    ");
  
    /*********************************************** 
        Pay Attention: 
     =============================================== 
        
           When using EL or JSTL, the following 
            
                User user = new User(); 
             
           will not work. 
        
       ============================================== 
        
    */           
       pageContext.setAttribute("user", new User());  
       pageContext.setAttribute("user2", new User());  
             
       //request.setAttribute("user", new User());  
         
    
      out.write("  \n");
      out.write("  \n");
      out.write("      \n");
      out.write("    <h4>Using EL</h4>  \n");
      out.write("    <p>");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${user.name }", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null, false));
      out.write("</p>  \n");
      out.write("    <p>");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${user.getName() }", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null, false));
      out.write("</p>  \n");
      out.write("  \n");
      out.write("    <h4>Using JSTL</h4>  \n");
      out.write("    <p>");
      if (_jspx_meth_c_005fout_005f0(_jspx_page_context))
        return;
      out.write("</p>  \n");
      out.write("    <p>");
      if (_jspx_meth_c_005fout_005f1(_jspx_page_context))
        return;
      out.write("</p>  \n");
      out.write("  \n");
      out.write("  \n");
      out.write("      \n");
      out.write("    ");
  
        String hello = "Hello World!";  
    
      out.write("  \n");
      out.write("    <h4>Using JSP Expression</h4>  \n");
      out.write("    <p>");
      out.print(hello);
      out.write("</p>  \n");
      out.write("      \n");
      out.write("</body>  \n");
      out.write("</html>  ");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              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);
    }
  }

  private boolean _jspx_meth_c_005fout_005f0(javax.servlet.jsp.PageContext _jspx_page_context)
          throws java.lang.Throwable {
    javax.servlet.jsp.PageContext pageContext = _jspx_page_context;
    javax.servlet.jsp.JspWriter out = _jspx_page_context.getOut();
    //  c:out
    org.apache.taglibs.standard.tag.rt.core.OutTag _jspx_th_c_005fout_005f0 = (org.apache.taglibs.standard.tag.rt.core.OutTag) _005fjspx_005ftagPool_005fc_005fout_0026_005fvalue_005fnobody.get(org.apache.taglibs.standard.tag.rt.core.OutTag.class);
    boolean _jspx_th_c_005fout_005f0_reused = false;
    try {
      _jspx_th_c_005fout_005f0.setPageContext(_jspx_page_context);
      _jspx_th_c_005fout_005f0.setParent(null);
      // /home.jsp(38,7) name = value type = null reqTime = true required = true fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
      _jspx_th_c_005fout_005f0.setValue((java.lang.Object) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${user2.name}", java.lang.Object.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null, false));
      int _jspx_eval_c_005fout_005f0 = _jspx_th_c_005fout_005f0.doStartTag();
      if (_jspx_th_c_005fout_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
        return true;
      }
      _005fjspx_005ftagPool_005fc_005fout_0026_005fvalue_005fnobody.reuse(_jspx_th_c_005fout_005f0);
      _jspx_th_c_005fout_005f0_reused = true;
    } finally {
      org.apache.jasper.runtime.JspRuntimeLibrary.releaseTag(_jspx_th_c_005fout_005f0, _jsp_getInstanceManager(), _jspx_th_c_005fout_005f0_reused);
    }
    return false;
  }

  private boolean _jspx_meth_c_005fout_005f1(javax.servlet.jsp.PageContext _jspx_page_context)
          throws java.lang.Throwable {
    javax.servlet.jsp.PageContext pageContext = _jspx_page_context;
    javax.servlet.jsp.JspWriter out = _jspx_page_context.getOut();
    //  c:out
    org.apache.taglibs.standard.tag.rt.core.OutTag _jspx_th_c_005fout_005f1 = (org.apache.taglibs.standard.tag.rt.core.OutTag) _005fjspx_005ftagPool_005fc_005fout_0026_005fvalue_005fnobody.get(org.apache.taglibs.standard.tag.rt.core.OutTag.class);
    boolean _jspx_th_c_005fout_005f1_reused = false;
    try {
      _jspx_th_c_005fout_005f1.setPageContext(_jspx_page_context);
      _jspx_th_c_005fout_005f1.setParent(null);
      // /home.jsp(39,7) name = value type = null reqTime = true required = true fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
      _jspx_th_c_005fout_005f1.setValue((java.lang.Object) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${user2.getName()}", java.lang.Object.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null, false));
      int _jspx_eval_c_005fout_005f1 = _jspx_th_c_005fout_005f1.doStartTag();
      if (_jspx_th_c_005fout_005f1.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
        return true;
      }
      _005fjspx_005ftagPool_005fc_005fout_0026_005fvalue_005fnobody.reuse(_jspx_th_c_005fout_005f1);
      _jspx_th_c_005fout_005f1_reused = true;
    } finally {
      org.apache.jasper.runtime.JspRuntimeLibrary.releaseTag(_jspx_th_c_005fout_005f1, _jsp_getInstanceManager(), _jspx_th_c_005fout_005f1_reused);
    }
    return false;
  }
}





引用

    附: 在 EL 表达式中的变量可以依附的 scope 对象

    只有定义在 scope 对象中的变量,才可以被其它的地方( EL)引用到。

    page
    变量被设置给 page 对象,则只能在本 jsp 内使用,不能在使用 <jsp:include> 调用该 jsp 的上级 jsp 中起作用。
    - 使用 <jsp:useBean> 标签创建的变量默认都是 page scope 。
    - 另外这些对象也都属于 page scope: out, response, pageContext, config, page, exception。

    request
    变量被设置给 request 对象,可以在本次访问所涉及到的的任何 jsp 页面中使用。
    通常多个 jsp 页面共同为一次访问提供结果。

    session
    变量被设置给 session 对象,可以在本次会话中的任意 jsp 页面中访问。

    application
    变量被设置给 applicaation 对象,可以在整个应用的任意 jsp 页面中访问。


      注:这种内置对象或上下文的用法在类库或模板设计方法中经常使用。比如, JSP有内置对象,JSTL也有内置对象(语法使用时的上下文环境),Struts 2 的标签也有内置对象及上下文环境(ValueStack)





四、 <c:set> 标签

引用


我们一直在关心在 scope 范围内怎样灵活设置变量。

除了在 JSP 页面的 Java 代码块 <% %> 中使用四个scope对象的 setAttribute() 方法外(当然,这是最常用和好用的方法),还可以使用: <c:set> 与 <jsp:useBean> 。

使用这两个标签时,都可以指定变量设置在那个 scope 对象中。也就是这两个标签都有一个名为 scope 的属性。




c:set 标签可以设置3种类型的变量到 scope 中(默认为 page Scope):

1、设置 纯文本字符 到 scope 中:
<c:set var="cName1" value="My Name"/>


2、设置 本地变量 到 scope 中:
<c:set var="cName2" value="<%= name %>"/>


3、设置 scope变量 到 scope 中:
<c:set var="cName3" value="${user.name}"/>



用法示例:
<%@ page isELIgnored="false"%>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c" %>
<%@ page contentType="text/html; charset=utf-8" language="java" %>
<%@ page import="com.eddy.pojo.User"%>
<html>
<body>


<%
	String name = "Hello World!";
	
	User user = new User("Admin");
	pageContext.setAttribute("user",user);
%>

	<c:set var="cName1" value="My Name"/>
	<c:set var="cName2" value="<%= name %>"/>
	<c:set var="cName3" value="${user.name}"/>
	
	<c:out value="${cName1}"></c:out><br/>
	<c:out value="${cName2}"></c:out><br/>
	<c:out value="${cName3}"></c:out><br/>
	
<hr/>

	name: <%= name %><br/>

	cName2: <%= pageContext.getAttribute("cName2") %><br/>
	cName3: <%= pageContext.getAttribute("cName3") %><br/>

</body>
</html>



输出:
My Name
Hello World!
Admin
——————————————
name: Hello World!
cName2: Hello World!
cName3: Admin



<c:set> 的第二种用法:用于修改 JSP scope 中的对象的某个属性值
<c:set target="${user}" property="name" value="John"/>

等价于:

user.setName("John");


 
<c:set> 用法示例:

    1、未指定 scope 时,使用 pageContext 对象对 c:set 对变量进行获取。
    <c:set var="streetName" value="${properties.street}" />
    <c:set var="cityName" value="${properties.city}" />
    <c:set var="stateName" value="${properties.state}" />
    <c:set var="startPoint" value="${streetName}, ${cityName}, +${stateName}" />


    // 使用 pageContext 对象,对 c:set 对变量进行获取
    <% String encodedStartPoint = java.net.URLEncoder.encode(
            (String)pageContext.getAttribute("startPoint"), "UTF-8");%>


    2、设置代码中的变量到 scope 中,从而在其它 c 标签中使用
<c:set var="language">
   <%= langTemp %>
</c:set>
<c:choose>
    <c:when test="${language=='en'}">
        <body class="bodytag-en">
    </c:when>
    <c:otherwise>
        <body>
    </c:otherwise>
</c:choose>


   
    3、在指定的 scope 中创建一个变量
<c:set var="currency" value="${user.currency}" scope="session" />



注:
1、使用 <c:remove var="currency"/> 移除所有 scope 中名为 currency 的变量
2、注意在一个jsp中引用其他jsp时(<jsp:include>),使用<c:set />时变量的范围。
      一般为当前jsp内起作用,也就是不指定scope时在当前页面中设置的变量,
      在子页面中时访问不到的(scope 默认为 page)。



引用

The <c:set> tag sets the value of an EL variable or the property of an EL variable in any of the JSP scopes (page, request, session, or application). If the variable does not already exist, it is created.

The JSP EL variable or property can be set either from the attribute value:

<c:set var="foo" scope="session" value="..."/>
or from the body of the tag:

<c:set var="foo">
     ...
</c:set>

http://docs.oracle.com/javaee/5/tutorial/doc/bnakh.html



五、 <jsp:useBean>标签

    如果变量已经存在 scope 中,可以使用 <c:set> 据此在 scope 中创建一些新的变量。
但是,如果变量根本就不存在呢?
    <jsp:useBean>:用于设置或初始化一个 JavaBean 类。如果 bean 已经在指定的 scope 中存在,则不会去创建,否则会新建一个 JavaBean,然后将其设置到 scope 中。

例子:
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page import="com.test.pojo.User" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
	<jsp:useBean id="user" class="com.test.pojo.User"/>

	<h4>Using EL</h4>
	<p>${user.name }</p>
	<p>${user.getName() }</p>
	
	
<%
     user = (User) pageContext.getAttribute("user");
	 user.setName("Hello, JSTL!");
	
%>
	<h4>Using JSTL</h4>
	<p><c:out value="${user.name}" /></p>
	<p><c:out value="${user.getName()}" /></p>
	
</body>
</html>


User class
package com.test.pojo;
public class User {		
	private String name = "Welcome, JSTL!";	
	
	public String getName(){
		return name;
	}
	
	public void setName(String name){
		this.name = name == null ? "null" : name ;
	}
}


结果输出:
引用

Using EL
Welcome, JSTL!
Welcome, JSTL!

Using JSTL
Hello, JSTL!
Hello, JSTL!



c:set 与  jsp:useBean 的区别
引用

*Difference betweenn c:set and jsp:useBean*

See the basic difference between c:set and jsp:useBean is:

First
c:set is a JSTL tag
while jsp:useBean is a JSP action.

Second thing,
you can use jsp:useBean either to retrieve a bean or create a bean object.
While c:set is used to set the property of an already existing bean not to create a bean or get a bean. c:set works somewhat similar to jsp:setProperty action for java beans.

And third thing,
there is no scope attribute for c:set(when you are using it with target attribute) JSTL tag as it is there for jsp:useBean JSP action.
And if you provide the value of target attribute as an EL expression, searching is from most restrictive scope to least restrictive scope.




六、EL 表达式 与 JSTL 标签的不同之处

问题1:JSTL 与 EL(Expression Language)的区别和联系?
阅读完“怎样避免在jsp中写逻辑代码”后,我停止了在jsp中写java代码片段的行为。因此我开始阅读和学习 JSTL,结果发现 JSTL 和 EL 之间有联系。但是我并不清楚这种联系。

下面是代码:
 <c:set var="test" value="JSTL Core Tags"></c:set>
 <c:out value="${test}"></c:out>

我只知道 <c:set 是 JSTL 标签,而 ${test} 是 EL (表达式语言)。

我的困惑是:
1. JSTL 可以单独使用吗?是否必须配合 EL ?如果不是必须,如何解释上面代码?
2. 如何最简单的只使用 EL 表达式?

-----------------------------
Answer:

EL 表达式最初只用于 JSTL 标签(或其它自定义标签)的属性中。
在后来的 JSP 定义版本中,允许 EL 单独在 JSP 中使用,用于简单属性的输出。例如:
${user.id}
可以把 user 对象的 id 属性写入到 jsp 中。但这并不表明 JSTL 就没有用处了,JSTL 可以提供:条件判断,循环输出,html 标签过滤,URLs,日期格、数字式化等功能。


问题2:Are session and sessionScope the same in JSP EL?

public class LoginAction extends ActionSupport {
    private String username;
    private String password;

    @Override
    public String execute() throws Exception {
        ActionContext ctx = ActionContext.getContext();
        Integer counter = (Integer)ctx.getApplication().get("counter");
        // put counter into application 
        ctx.getApplication().put("counter", counter);
        // put username into session
        ctx.getSession().put("user", username);
        if (getUsername().equals("crazyit.org")
                && getPassword().equals("leegang")) {
            ctx.put("tip", "Login Success! ");
            return SUCCESS;
        }
        else {
            ctx.put("tip", "Login Falied!");
            return ERROR;
        }        
    }
}


I put "counter" in application "user" in session and "tip" in ActionContext. In JSP I can use ${session.user} and ${sessionScope.user} to reference the "user" property. ${request.tip} and ${requestScope.tip} to reference tip.

My questions:

Are session, request, application the same as sessionScope, requestScope, applicationScope in EL?
What's the relationship between ActionContext and request(requestScope)?
P.S.:

I test ${request == requestScope} which is true, this means they are the same?




回答:

/*


<%--

http://*.com/a/17592665/2893073

By default 
            page, 
            request, 
            session,
            application

objects are available to JSP pages. 
So you can access then using EL syntax.

Except the above objects,
And following table shows IMPLICIT objects available to EL.

	       Implicit object            Description
	1.     pageScope        Scoped variables from page scope
	2.     requestScope     Scoped variables from request scope
	3.     sessionScope     Scoped variables from session scope
	4.     applicationScope Scoped variables from application scope
	5.     param            Request parameters as strings
	6.     paramValues      Request parameters as collections of strings
	7.     header           HTTP request headers as strings
	8.     headerValues     HTTP request headers as collections of strings
	9.     initParam        Context-initialization parameters
	10.    cookie           Cookie values
	11.    pageContext      The JSP PageContext object for the current page
	
	So session and sessionScope are same but differs in context they are used.
	More specifically session is object and sessionScope is map (key, value) of Attribute 
	and its value.
	
	If you say ${session.sessionAttr} it refers to session object available to JSP page.
	If you say ${sessionScope.sessionAttr} it refers to IMPLICIT session object available to EL.
	if you just say {attrName} it will search attrName in all scope,
	   from page to application scope.
	   
	--------------   
	   
	EL duplicates those objects for self style usage. 
	But it may cause confusion to jsp beginners. 

--%>


*/






引用:
Scope of JSP Objects
- http://javapapers.com/jsp/explain-the-scope-of-jsp-objects/

JSTL Core: <c:set> Tag
- http://www.tutorialspoint.com/jsp/jstl_core_set_tag.htm

c:set Examples
- http://javarevisited.blogspot.com/2012/02/jstl-tag-examples-in-jsp-java-j2ee.html

jsp:useBean Action Tag
- http://www.javatpoint.com/jsp-useBean-action

Exact difference and relation between JSTL and expression-language
- http://*.com/questions/15848251/







-
转载请注明
原文出处:http://lixh1986.iteye.com/blog/2324611











-
相关标签: jsp jstl scope