<jsp:useBean>標簽
會調用java對象的無參構造方法,來創建實例。
<jsp:useBean>標簽是用來搭配JavaBean元件的標准標簽,這里指的JavaBean是滿足以下條件的Java對象:
1、必須實現java.io.Serializable接口
2、具有無參數的構造器
3、沒有公開(public)的類變量
4、具有公開的設值方法(Setter)與取值方法(Getter)
但是在實際的測試中沒有實現序列化接口也沒有問題。
Demo:
package com.test; public class AddServiceImpl { public String add() { return "1 + 2 = 5"; } }
<%@page contentType="text/html" pageEncoding="UTF-8" %>
<jsp:useBean id="addService" class="com.test.AddServiceImpl"/>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<p><%= addService.add()%></p>
</body>
</html>
測試地址:http://127.0.0.1/index.jsp
運行結果:1 + 2 = 5
查看轉譯后的servlet源碼有如下內容:
com.test.AddServiceImpl addService = null; addService = (com.test.AddServiceImpl) _jspx_page_context.getAttribute("addService", javax.servlet.jsp.PageContext.PAGE_SCOPE); if (addService == null){ addService = new com.test.AddServiceImpl(); _jspx_page_context.setAttribute("addService", addService, javax.servlet.jsp.PageContext.PAGE_SCOPE); } out.print( addService.add());
源碼分析
使用<jsp:useBean id="addService" class="com.test.AddServiceImpl"/>聲明一個java對象后,servlet會去pageContext域里根據指定的id值去尋找這個java對象,如果找不到,使用無參的構造方法創建並且再把它設置到pageContext作用域里。
接着就可以使用設定的id值或者說pageContext域的key——addService來直接使用這個對象。
使用<jsp:useBean>時,還可以指定scope屬性,可以指定的值有page(默認)、request、session與application。這樣就先會到指定屬性范圍中尋找該實例,如果找到就直接使用;找不到也不會到其它作用域里去找,而是創建一個新對象並放入到指定的指定的作用域里。
使用<jsp:useBean>時,還可以指定type屬性。type屬性的設置可以是一個抽象類,也可以是一個接口。如果只設置type而沒有設置class屬性,則必須確定在某個屬性范圍中已經存在所要的對象,否則會發生InstantiationException異常。比如:
<jsp:useBean id="user" type="com.test.UserBase" class="com.test.User" scope="session"/>
這樣產生的 Servlet 中,將會有以下的片段:
com.test.UserBase user = null; synchronized (session) { user = (com.test.UserBase) _jspx_page_context.getAttribute("user", javax.servlet.jsp.PageContext.SESSION_SCOPE); if (user == null){ user = new com.test.User(); _jspx_page_context.setAttribute("user", user, javax.servlet.jsp.PageContext.SESSION_SCOPE); } }
<jsp:setProperty>標簽
會調用java對象public的setter方法。
1、獲取客戶端參數
Demo
package com.test; public class User { private String name; private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
<%@page contentType="text/html" pageEncoding="UTF-8" %> <jsp:useBean id="user" class="com.test.User"/> <jsp:setProperty name="user" param="name" property="name"></jsp:setProperty> <jsp:setProperty name="user" param="age" property="age"></jsp:setProperty> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello</title> </head> <body> <p> 姓名:<jsp:getProperty name="user" property="name"/><br> 年齡:<jsp:getProperty name="user" property="age"/> </p> </body> </html>
測試地址:http://127.0.0.1/index.jsp?name=zs&age=18
響應結果:
姓名:zs
年齡:18
如果是獲取客戶端參數,有三種寫法:
寫法一:
<jsp:setProperty name="user" param="name" property="name"></jsp:setProperty>
<jsp:setProperty name="user" param="age" property="age"></jsp:setProperty>
寫法二:
<jsp:setProperty name="user" property="name"></jsp:setProperty>
<jsp:setProperty name="user" property="age"></jsp:setProperty>
如果不指定請求參數名稱,JSP的自省機制會判斷是否有相同名稱的請求參數,有的話就找出並調用對應的setter方法。
寫法三:
<jsp:setProperty name="user" property="*"></jsp:setProperty>
在property屬性設置為“*”時,表示將自動尋找請求參數,如果請求參數名稱為xxx,就將請求參數值使用setXxx()方法。
自省機制可以自動轉換請求參數字符串為對應屬性的基本類型。
2、直接賦值
比如:<jsp:setProperty name="user" property="password" value="123456"/>
3、<jsp:setProperty>的name屬性說明
在產生的Servlet代碼中,會使用PageContext的findAttribute(),依次從page、request、session、application中查找看看有無name指定的屬性名稱,找到的話,再通過反射機制找出JavaBean上的setXxx()方法並執行。
<jsp:getProperty>標簽
<jsp:getProperty>基本上就只有一種用法:<jsp:getProperty name="user" property="name"/>。
這會通過PageContext的findAttribute()從page、request、session、application中依序查找user屬性,並通過getName()方法取得值。
兩種不兩只的寫法
一、在使用<jsp:useBean>時可以一並設置屬性值
<jsp:useBean id="user" class="com.test.User" scope="session">
<jsp:setProperty name="user" property="*" />
</jsp:useBean>
這樣轉譯后產生以下代碼:
synchronized (session) { user = (com.test.User) _jspx_page_context.getAttribute("user", javax.servlet.jsp.PageContext.SESSION_SCOPE); if (user == null){ user = new com.test.User(); _jspx_page_context.setAttribute("user", user, javax.servlet.jsp.PageContext.SESSION_SCOPE); org.apache.jasper.runtime.JspRuntimeLibrary.introspect(_jspx_page_context.findAttribute("user"), request); } }
二、分別編寫
<jsp:useBean id="user" class="com.test.User" scope="session"/>
<jsp:setProperty name="user" property="*" />
這樣轉譯后產生以下代碼:
synchronized (session) { user = (com.test.User) _jspx_page_context.getAttribute("user", javax.servlet.jsp.PageContext.SESSION_SCOPE); if (user == null){ user = new com.test.User(); _jspx_page_context.setAttribute("user", user, javax.servlet.jsp.PageContext.SESSION_SCOPE); } } org.apache.jasper.runtime.JspRuntimeLibrary.introspect(_jspx_page_context.findAttribute("user"), request);
如果使用后一種寫法,則無論找到還是新建JavaBean對象,都一定會使用內省機制來設值。
