JSP入门初级教程

JSP入门初级教程之Actions的使用

 JSP actions 使用您可以动态的插入一个文件,重用JavaBeans组件,前进到另一个页面,或为Java 插件生成一个HTML。可以使用的action 有:

  (1) jsp:include --在页面被请求时包含进一个文件。

  (2) jsp:useBean--找到或实例化一个JavaBean。

  (3) jsp:setProperty--设置一个JavaBean属性。

  (4) jsp:getProperty--将JavaBean的属性插入到输出。

  (5) jsp:forward--让请求者可以向前到一个新的页面。

  (6) jsp:plugin--用OBJECT或EMBED标签为Java plugins生成特定的浏览器的代码。

  1、jsp:include Action

  这个action使您可以在即将生成的页面上包含进一些文件:

<jsp:include page="relative URL" flush="true" />
  
  与include directive不同,这个action是在页面被请求时才将文件包含进来,而,include directive则是在JSP页面被转换为servlet时包含文件。为了提高效率,include action做了一点小小的牺牲,即,它不允许被包含的页面含有一般的JSP代码(例如,不可设置HTTP头),但是,它具有显著的灵活性,如下面的JSP 代码,它实现将四个不同的片段插入如下的页面。每一次当标题改变的时候,您仅需修改这四个文件而无须更改主要的JSP 页面。

  WhatsNew.jsp

<HTML>
<HEAD>
<TITLE> JSP教程</TITLE>
<BODY >
<CENTER>
<TABLE BORDER=5 BGCOLOR="#EF8429">
<TR><TH CLASS="TITLE"> What"s New at Chinese comic sites</TABLE>
</CENTER>
<P>
Here is a summary of our four most recent news stories:
<OL>
<LI><jsp:include page="news/Item1.html" flush="true"/>
<LI><jsp:include page="news/Item2.html" flush="true"/>
<LI><jsp:include page="news/Item3.html" flush="true"/>
<LI><jsp:include page="news/Item4.html" flush="true"/>
</OL>
</BODY>
</HTML>

  当然您可以定义自己? ML文件,但有一点请注意:

  您应该将文件放到您的JSP目录下的news目录内。

  jsp:useBean Action 的使用

  一、 语法:

<jsp:useBean
id="beanInstanceName"
scope="page|request|session|application"
{ class="package.class" |
type="package.class" |
class="package.class" type="package.class" |
beanName="{package.class | <%= expression %>}" type="package.class"
}
{ /> |
其他元素
</jsp:useBean>
}

  这个action使您能将一个JavaBean装入一个JSP页面。这是一个非常有用的能力,因为它使您可以使用可重用的JAVA类而不需牺牲性能。最简单的语法用于指定一个bean:

<jsp:useBean id="name" class="package.class" />


  这通常意味着“实例化一个类的对象通过指定一个类,并将之与一个通过id指定名称的变量绑定”。然而,就象我们看到的,您可以指定一个scope属性来使得bean不仅仅与当前的页面相联系。在这种情形下,得到一个对已存在的bean的引用是非常有用的,而且,仅当没有相同的id和scope的bean存在时才创建一个新的。现在,您已有了bean,您可以通过jsp:setProperty来修改它,或者,通过使用之前用id指定的名字来使用scriptlet或明确的调用方法。当您说“这个bean有一个称为foo的X类型的属性”,您真正的意思是“这个类有一个称为getFoo的方法,它返回X类型的某类值,还有另一个方法称为setFoo,它以X为参数。”这jsp:setProperty action 将在下一单元详细的介绍,但是现在您既可以给出一个明确的值,给出一个属性来说明此值是从request的参数继承而来,也可以仅仅列出属性来标志此值应该从与属性名同名的参数继承而来。您可以通过调用适用的getXxx方法,或更普遍的,使用jsp:getProperty action,来得到已存在的JSP表达式或scriptlet属性。

  请注意,为bean指定的类必须在服务器的规则的类路径下,而不是用来保留当改变时自动装载的类的路径。例如,在Java Web Server上,它和它所用的类必须到类的目录或在lib目录下的一个jar文件内,而不是在servlets的目录下。

  下面让我们来看一个非常简单的例子,它装载一个bean并且设置/得到一个简单的串参数。

BeanTest.jsp

<HEAD>
<TITLE>Reusing JavaBeans in JSP</TITLE>
</HEAD>
<BODY>
<CENTER>
<TABLE BORDER=5>
<TR><TH CLASS="TITLE">
Reusing JavaBeans in JSP</TABLE>
</CENTER>
<P>
<jsp:useBean id="test" class="hall.SimpleBean" />
<jsp:setProperty name="test"
property="message"
value="Hello WWW" />
<H1>Message: <I>
<jsp:getProperty name="test" property="message" />
</I></H1>
</BODY>

  SimpleBean.java

  以下是bean的原代码:

package hall;
public class SimpleBean {
 private String message = "No message specified";
 public String getMessage() {
  return(message);
 }
 public void setMessage(String message) {
  this.message = message;
 }
}

  运行结果为:页面输出: Reusing JavaBeans in JSP

  Message:Hello WWW

  二、jsp:useBean 的详细用法

  最简单的使用bean的方式是:

  
<jsp:useBean id="name" class="package.class"/>
  为了装载bean,需要用jsp:setProperty和 jsp:getProperty来修改和检索bean的属性。且,还有两种别的选项。首先,您可以使用容器的格式,也就是:

<jsp:useBean ...>
Body
</jsp:useBean>

  要指出的是,Body部分应该仅在bean第一次实例化时被执行,而不是在每次被找到和使用时。Beans能够被共享,因此,并不是所有的jsp:useBean 陈述都产生一个新的bean的实例。其次,除了id 或class以外,还有三种属性您可以使用:scope,type,和beanName。这些属性总结如下:

属性含义
id给一个变量命名,此变量将指向bean。如果发现存在一个具有相同的id和scope 的bean则使用之而不新建一个。
class指出bean的完整的包名。
scope指明bean在之上可以被使用的前后关系。有四个可能的值:page,request,session,和application。缺省为page,表明bean仅在当前页可用(保存在当前的PageContext中)。request的一个值表明bean仅用于当前客户端的请求(保存在ServletRequest对象中)。Session的值指出在当前的HttpSession的生命周期内,对象对所有的页面可用。 最后,application的值指出对象对所有共享ServletsContext的页面可以使用。使用jsp:useBean 仅在没有相同的id和scope 的bean时创建一个新的bean,如果已有则使用之,并忽略以jsp:useBean标志开始和结尾的代码。
type指明将指向对象的变量的类型。这必须与类名相匹配或是一个超类或者是一个实现类的接口。记住,变量的名由id属性来指定。
beanName赋予bean一个名字,您应该在Beans的实例化方法中提供。它允许您给出type和一个beanName,并省略类属性。
    三、jsp:setProperty Action

  语法:

<jsp:setProperty
name="beanInstanceName"
{
 property="*" | property="propertyName" [ param="parameterName" ] | property="propertyName" value="{string | <%= expression %>}"
}
/>

  在前面我们就知道了可以使用 jsp:setProperty 来为一个bean的属性赋值。您可以使用两种方式实现它。其一是,在jsp:useBean后(而不是在之内)使用jsp:setProperty:

<jsp:useBean id="myName" ... />
...
<jsp:setProperty name="myName"
property="someProperty" ... />

  在这种方式中,jsp:setProperty 将被执行无论是否已有一个具有相同的id和scope的bean存在。另一种方式是,jsp:setProperty出现在jsp:useBean 元素内,如:

<jsp:useBean id="myName" ... >
...
<jsp:setProperty name="myName" property="someProperty" ... />
</jsp:useBean>

  此种情况下,jsp:setProperty仅在新的对象被实例化时才执行。

  以下是四种jsp:setProperty的可用的属性:

属性用法
name这是一个必选属性。它指出哪一个bean的属性将被设置。jsp:usebean必须出现在jsp:setProperty之前。
property这是一个必选属性。表明您将设置哪一个属性。然而,有一个特殊的情况:如果以"*"为值意味着,所有的名称与bean的属性匹配的request参数都将被传递到相应的属性设置方法。
value这是一个可选属性。它指定被设置的属性的值。字符串的值通过相应的对象或包的标准的valueOf方法将自动的转换为numbers,boolean,Boolean,byte,Byte,char,和Character。例如,boolean或Boolean属性的值“true”将通过Boolean.valueOf方法转化,而,一个int或Integer属性的值“42”将通过Integer.valueOf转化。您不能同时使用value和param属性,但,两个都不用是允许的。
param这是一个可选属性。它指明了bean的属性应该继承的request的参数。如果当前的request没有这样的一个参数,就什麽也不做:系统并不将null传给设置属性的方法。因此,您可以使用bean的缺省值。例如下面的这段程序执行“将numberOfItems属性设置为任意numItems request参数的值,如果有这样的一个request参数,否则什么也不做。”

<jsp:setProperty name="orderBean" property="numberOfItems" param="numItems" />
  

  如果您将value和param同时缺省,这和您将param的名称设为bean的属性名相同一样。您可以通过将name的值设置为”*”和省略value和param来自动的使用与bean的属性相应的request的属性。在这种情况下,服务器将反复的查找可用的属性和request参数来匹配具有相同名字的。

  四、jsp:getProperty Action

  语法:

<jsp:getProperty name="beanInstanceName" property="propertyName" />
 
  这个属性检索出bean的属性的值并将之转化为一个字符串,然后将之插入到输出。它有两个必选属性:name,在之前用jsp:useBean引入的名称,property,必须被插入值的属性。

JSP入门初级教程之Session的使用

 TTP协议是无状态的,即信息无法通过HTTP协议本身进传递。为了跟踪用户的操作状态,ASP应用SESSION对象。JSP使用一个叫HttpSession的对象实现同样的功能。HTTPSession 是一个建立在cookies 和URL-rewriting上的高质量的界面。Session的信息保存在服务器端,Session的id保存在客户机的cookie中。事实上,在许多服务器上,如果浏览器支持的话它们就使用cookies,但是如果不支持或废除了的话就自动转化为URL-rewriting,session自动为每个流程提供了方便地存储信息的方法。

  Session一般在服务器上设置了一个30分钟的过期时间,当客户停止活动后自动失效。Session 中保存和检索的信息不能是基本数据类型如 int, double等,而必须是java的相应的对象,如Integer, Double。

  Httpsession具有如下API:


  getId 此方法返回唯一的标识,这些标识为每个session而产生。当只有一个单一的值与一个session联合时,或当日志信息与先前的sessions有关时,它被当作键名用。

  GetCreationTime 返回session被创建的时间。最小单位为千分之一秒。为得到一个对打印输出很有用的值,可将此值传给Date constructor 或者GregorianCalendar的方法setTimeInMillis。

  GetLastAccessedTime 返回session最后被客户发送的时间。最小单位为千分之一秒。

  GetMaxInactiveInterval 返回总时间(秒),负值表示session永远不会超时。

  getAttribute 取一个session相联系的信息。(在jsp1.0中为 getValue)

  Integer item = (Integer) session.getAttrobute("item") //检索出session的值并转化为整型

  setAttribute 提供一个关键词和一个值。会替换掉任何以前的值。(在jsp1.0中为putValue)

  session.setAttribute("ItemValue", itemName); // ItemValue 必须不是must简单类型

  
在应用中使用最多的是getAttribute和setAttribute。现以一个简单的例子来说明session的应用,  test1.jsp(信息写入session),test2.jsp(从session读出信息)。

test1.jsp

<HTML>

<HEAD>

<TITLE> Document </TITLE>

</HEAD>

<BODY BGCOLOR="#FFFFFF">
session.setAttribute("str",new String(“this is test”));
</BODY>

</HTML>
test2.jsp
<HTML>

<HEAD>
<TITLE> New Document </TITLE>

</HEAD>

<BODY BGCOLOR="#FFFFFF">
<%
String ls_str=null;
ls_str=(String)session.getAttribute("str");
out.println(“从session里取出的值为:”+ls_str);
%>
</BODY>

</HTML>



JSP入门初级教程之Taglib Directiv

  JSP页面上使用你可以使用Taglib Directive来自定义标签定义一个标签库和前缀。

  
其语法:

<%@ taglib uri="URIToTagLibrary" prefix="tagPrefix" % >

  示例:

<%@ taglib uri="http://www.jspcentral.com/tags" prefix="public" %>
<public:loop>
.
</public:loop>

  描述:

<%@ taglib %>指示(directive)允许您使用自定义的标签,为标签库命名,并指定它们的前缀。

  术语custom tag 不仅仅是指标签,而且还指元素。因为JSP文件可以转化为XML,理解标签和元素的联系是很重要的。标签仅仅是一种标志(markup),是JSP元素的一部分。JSP元素是一个JSP语法单元,这个语法单元在XML中等价于一个开始标签和结束标签。元素可以包含其他的文本,标签,或元素。例如,一个jsp:plugin元素总是以<jsp:plugin>标签开始和一个</jsp:plugin>结尾,而且,还可以包含一个<jsp:params>元素和<jsp:fallback>元素。

  在您在JSP文件中使用自定义的标签前,您必须使用一个<%@ taglib %>指示。一个JSP文件中您可以使用多个<%@ taglib %>指示,但,在每一个前面定义的前缀必须是唯一的。

  属性详解:

 

Uri = “URIToTagLibrary”
  统一资源定义(URI——The Uniform Resource Identifier)
  一个URI可以是以下的形式:
  The Uniform Resource LocatoResource Name)。
c

JSP入门初级教程之plugin的使用

 jsp:plugin Action 使您能插入所需的特定的浏览器的OBJECT或EMBED元素来指定浏览器运行一个JAVA Applet所需的插件。

  语法:

<jsp:plugin type="bean|applet" code="classFileName" codebase="classFileDirectoryName"
[ name="instanceName" ]
[ archive="URIToArchive, ..." ]
[ align="bottom|top|middle|left|right" ]
[ height="displayPixels" ]
[ width="displayPixels" ]
[ hspace="leftRightPixels" ]
[ vspace="topBottomPixels" ]
[ jreversion="JREVersionNumber | 1.1" ]
[ nspluginurl="URLToPlugin" ]
[ iepluginurl="URLToPlugin" ] >
[ <jsp:params>
[ <jsp:param name="parameterName"
value="{parameterValue | <%= expression %>}" /> ]+
</jsp:params> ]
[ <jsp:fallback> text message for user </jsp:fallback> ]
</jsp:plugin>
示例:
<jsp:plugin type=applet code="Molecule.class" codebase="/html">
<jsp:params>
<jsp:param name="molecule" value="molecules/benzene.mol" />
</jsp:params>
<jsp:fallback>
<p>Unable to load applet</p>
</jsp:fallback>
</jsp:plugin>
属性详解

属性
用法

type = “bean | applet”
插件将执行的对象的类型。您必须在bean或applet中指定一个,因为,这个属性没有缺省值。

class=”classFileName
插件将执行的JAVA类文件的名称。在名称中您必须包含扩展名。且此文件必须在用“codebase”属性指明的目录下。

codebase=“classFileDirectoryName”
包含插件将运行的JAVA类的目录或指向这个目录的路径。缺省为此JSP文件的路径。

name=”instanceName”
Bean或 applet的实例的名称。使得被同一个JSP文件调用的bean或 applet之间的通信成为可能。

archive = “URLToArchive,…”
以逗号分隔的路径名列表。是那些用以codebase指定的目录下的类装载器预装载的存档文件所在的路径名。通常,这些存档文件通过网络被安全的加载,可以显著的提高applet的性能。


注释和字符引用习惯

  您可以使用一些特定的元素来插入注释和一些通常是作为特殊标志的字符。以下是一个总结:

语法
目的
<%-- 注释 --%>JSP形式的注释。将被JSP-to-scriptlet编译器所忽略。任何内嵌JSP scripting elements,directives,或actins都将被忽略。例:

<%@ page language="java" %>
<html>
<head><title>A Comment Test</title></head>
<body>
<h2>A Test of Comments</h2>
<%-- 这部分注释将不会在查看源代码的时候看到 --%>
</body>
</html>
<!-- 注释-->HTML形式的注释。直接传送到最终的HTML。任何内嵌JSP scripting elements,directives,或actins都将被正常的执行。例:
<!-- This page was loaded on
<%= (new java.util.Date()).toLocaleString() %> -->
查看源代码时将看到:
<!-- This page was loaded on January 1, 2000 -->
</%在template text(静态HTML)中,当您想在页面上输出这个特殊符号(<%)时请如此书写。
%/>在scripting elements中使用,作用与上面的“</%”类似。
/’在使用了“’”的属性中表明是字符“’”。当然,您也可以使用“””来作为区分。例:’ pig”fhjgj” ’,或,’pig/’fhjgj/’’
/”在使用了“””的属性中表明是字符“””。当然,您也可以使用“’”来作为区分。例:” pig’fhjgj’”,或,”pig/”fhjgj/””
%/>在属性中的“%>”。
</%在属性中的“<%”。

JSP入门初级教程之实现页面跳转

  JSP中使用jsp forward Action来实现页面的跳转功能。

  
语法:

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


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


<jsp:param name="parameterName"


value="{parameterValue|<%= expression %>}"/>+</jsp:forward>

  这个action使您可以将request向前到另外一个页面。它只有一个属性,page。Page应有一个相对的URL组成。这可以是一个静态的值或者是能够在被请求的时候计算得到的值,就如下面两个例子一般:

<jsp:forward page="/utils/errorReporter.jsp"/>
<jsp:forward page="<%= someJavaExpression %>"/>
!supportEmptyParas]>


  现在以一个具体例子来说明:在test1.jsp中使用forward使其跳转到test2.jsp页面中。

  Test1.jsp

<HTML>
<HEAD>
<TITLE>forward test</TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<!--跳转到test2.jsp--!>
<jsp:forward page="/test2.jsp"/>
</BODY>
</HTML>
!supportEmptyParas]>


  test2.jsp

<HTML>
<HEAD>
<TITLE> forward test </TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<%out.println("这是jsp2.jsp页面产生出的输出");%>
</BO #@62;
</HTML>
!supportEmptyParas]>

  运行test1.jsp,可在浏览器中看见:"这是jsp2.jsp页面产生出的输出"的输出信息。但是如果你在test1.jsp和test2.jsp这两个页面中有参数传递怎么办呢?用get方式吧,不但总的长度有限制,使用现在十分不方便,而且有时候还不安全。其实我们完全可以使用jsp1.1中给forward里提供的para属性就可以解决。现以test3.jsp和test4.jsp来说明。

!supportEmptyParas]>


Test1.jsp
<HTML>
<HEAD>
<TITLE> forward test </TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<jsp:forward page="/test4.jsp">
<jsp:param name="name" value="powerman"/>
<jsp:param name="address" value=" 北京西大街188号"/>
</jsp:forward>
</BODY>
</HTML>
!supportEmptyParas]>


test2.jsp
<HTML>
<HEAD>
<TITLE>forward test</TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<%
out.println("这是jsp4.jsp页面产生出的输出"+"<br>");
out.println("姓名:"+request.getParameter("name")+"<br>");
out.println("地址:"+request.getParameter("address")+"<br>");
!supportEmptyParas]>


%>
</BODY>
</HTML>


  运行test3.jsp,可在浏览器中看见输出信息


  "这是jsp4.jsp页面产生出的输出
  姓名:powerman
  地址:北京西大街188号"


  现在以一个具体例子来说明:在test1.jsp中使用forward使其跳转到test2.jsp页面中。

  Test1.jsp

<HTML>
<HEAD>
<TITLE>forward test</TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<!--跳转到test2.jsp--!>
<jsp:forward page="/test2.jsp"/>
</BODY>
</HTML>
!supportEmptyParas]>


  test2.jsp

<HTML>
<HEAD>
<TITLE> forward test </TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<%out.println("这是jsp2.jsp页面产生出的输出");%>
</BO #@62;
</HTML>
!supportEmptyParas]>

  运行test1.jsp,可在浏览器中看见:"这是jsp2.jsp页面产生出的输出"的输出信息。但是如果你在test1.jsp和test2.jsp这两个页面中有参数传递怎么办呢?用get方式吧,不但总的长度有限制,使用现在十分不方便,而且有时候还不安全。其实我们完全可以使用jsp1.1中给forward里提供的para属性就可以解决。现以test3.jsp和test4.jsp来说明。

!supportEmptyParas]>


Test1.jsp
<HTML>
<HEAD>
<TITLE> forward test </TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<jsp:forward page="/test4.jsp">
<jsp:param name="name" value="powerman"/>
<jsp:param name="address" value=" 北京西大街188号"/>
</jsp:forward>
</BODY>
</HTML>
!supportEmptyParas]>


test2.jsp
<HTML>
<HEAD>
<TITLE>forward test</TITLE>
!supportEmptyParas]>


</HEAD>
!supportEmptyParas]>


<BODY BGCOLOR="#FFFFFF">
<%
out.println("这是jsp4.jsp页面产生出的输出"+"<br>");
out.println("姓名:"+request.getParameter("name")+"<br>");
out.println("地址:"+request.getParameter("address")+"<br>");
!supportEmptyParas]>


%>
</BODY>
</HTML>


  运行test3.jsp,可在浏览器中看见输出信息


  "这是jsp4.jsp页面产生出的输出
  姓名:powerman
  地址:北京西大街188号"

JSP入门初级教程之Actions的使用

  JSP actions 使用您可以动态的插入一个文件,重用JavaBeans组件,前进到另一个页面,或为Java 插件生成一个HTML。可以使用的action 有:

  (1) jsp:include --在页面被请求时包含进一个文件。

  (2) jsp:useBean--找到或实例化一个JavaBean。

  (3) jsp:setProperty--设置一个JavaBean属性。

  (4) jsp:getProperty--将JavaBean的属性插入到输出。

  (5) jsp:forward--让请求者可以向前到一个新的页面。

  (6) jsp:plugin--用OBJECT或EMBED标签为Java plugins生成特定的浏览器的代码。

  1、jsp:include Action

  这个action使您可以在即将生成的页面上包含进一些文件:

<jsp:include page="relative URL" flush="true" />
  
  与include directive不同,这个action是在页面被请求时才将文件包含进来,而,include directive则是在JSP页面被转换为servlet时包含文件。为了提高效率,include action做了一点小小的牺牲,即,它不允许被包含的页面含有一般的JSP代码(例如,不可设置HTTP头),但是,它具有显著的灵活性,如下面的JSP 代码,它实现将四个不同的片段插入如下的页面。每一次当标题改变的时候,您仅需修改这四个文件而无须更改主要的JSP 页面。

  WhatsNew.jsp

<HTML>
<HEAD>
<TITLE> JSP教程</TITLE>
<BODY >
<CENTER>
<TABLE BORDER=5 BGCOLOR="#EF8429">
<TR><TH CLASS="TITLE"> What"s New at Chinese comic sites</TABLE>
</CENTER>
<P>
Here is a summary of our four most recent news stories:
<OL>
<LI><jsp:include page="news/Item1.html" flush="true"/>
<LI><jsp:include page="news/Item2.html" flush="true"/>
<LI><jsp:include page="news/Item3.html" flush="true"/>
<LI><jsp:include page="news/Item4.html" flush="true"/>
</OL>
</BODY>
</HTML>

  当然您可以定义自己? ML文件,但有一点请注意:

  您应该将文件放到您的JSP目录下的news目录内。

  jsp:useBean Action 的使用

  一、 语法:

<jsp:useBean
id="beanInstanceName"
scope="page|request|session|application"
{ class="package.class" |
type="package.class" |
class="package.class" type="package.class" |
beanName="{package.class | <%= expression %>}" type="package.class"
}
{ /> |
其他元素
</jsp:useBean>
}

  这个action使您能将一个JavaBean装入一个JSP页面。这是一个非常有用的能力,因为它使您可以使用可重用的JAVA类而不需牺牲性能。最简单的语法用于指定一个bean:

<jsp:useBean id="name" class="package.class" />

  这通常意味着“实例化一个类的对象通过指定一个类,并将之与一个通过id指定名称的变量绑定”。然而,就象我们看到的,您可以指定一个scope属性来使得bean不仅仅与当前的页面相联系。在这种情形下,得到一个对已存在的bean的引用是非常有用的,而且,仅当没有相同的id和scope的bean存在时才创建一个新的。现在,您已有了bean,您可以通过jsp:setProperty来修改它,或者,通过使用之前用id指定的名字来使用scriptlet或明确的调用方法。当您说“这个bean有一个称为foo的X类型的属性”,您真正的意思是“这个类有一个称为getFoo的方法,它返回X类型的某类值,还有另一个方法称为setFoo,它以X为参数。”这jsp:setProperty action 将在下一单元详细的介绍,但是现在您既可以给出一个明确的值,给出一个属性来说明此值是从request的参数继承而来,也可以仅仅列出属性来标志此值应该从与属性名同名的参数继承而来。您可以通过调用适用的getXxx方法,或更普遍的,使用jsp:getProperty action,来得到已存在的JSP表达式或scriptlet属性。

  请注意,为bean指定的类必须在服务器的规则的类路径下,而不是用来保留当改变时自动装载的类的路径。例如,在Java Web Server上,它和它所用的类必须到类的目录或在lib目录下的一个jar文件内,而不是在servlets的目录下。
  下面让我们来看一个非常简单的例子,它装载一个bean并且设置/得到一个简单的串参数。

BeanTest.jsp

<HEAD>
<TITLE>Reusing JavaBeans in JSP</TITLE>
</HEAD>
<BODY>
<CENTER>
<TABLE BORDER=5>
<TR><TH CLASS="TITLE">
Reusing JavaBeans in JSP</TABLE>
</CENTER>
<P>
<jsp:useBean id="test" class="hall.SimpleBean" />
<jsp:setProperty name="test"
property="message"
value="Hello WWW" />
<H1>Message: <I>
<jsp:getProperty name="test" property="message" />
</I></H1>
</BODY>

  SimpleBean.java

  以下是bean的原代码:

package hall;
public class SimpleBean {
 private String message = "No message specified";
 public String getMessage() {
  return(message);
 }
 public void setMessage(String message) {
  this.message = message;
 }
}

  运行结果为:页面输出: Reusing JavaBeans in JSP

  Message:Hello WWW

  二、jsp:useBean 的详细用法

  最简单的使用bean的方式是:

  
<jsp:useBean id="name" class="package.class"/>
  为了装载bean,需要用jsp:setProperty和 jsp:getProperty来修改和检索bean的属性。且,还有两种别的选项。首先,您可以使用容器的格式,也就是:

<jsp:useBean ...>
Body
</jsp:useBean>

  要指出的是,Body部分应该仅在bean第一次实例化时被执行,而不是在每次被找到和使用时。Beans能够被共享,因此,并不是所有的jsp:useBean 陈述都产生一个新的bean的实例。其次,除了id 或class以外,还有三种属性您可以使用:scope,type,和beanName。这些属性总结如下:

属性含义
id给一个变量命名,此变量将指向bean。如果发现存在一个具有相同的id和scope 的bean则使用之而不新建一个。
class指出bean的完整的包名。
scope指明bean在之上可以被使用的前后关系。有四个可能的值:page,request,session,和application。缺省为page,表明bean仅在当前页可用(保存在当前的PageContext中)。request的一个值表明bean仅用于当前客户端的请求(保存在ServletRequest对象中)。Session的值指出在当前的HttpSession的生命周期内,对象对所有的页面可用。 最后,application的值指出对象对所有共享ServletsContext的页面可以使用。使用jsp:useBean 仅在没有相同的id和scope 的bean时创建一个新的bean,如果已有则使用之,并忽略以jsp:useBean标志开始和结尾的代码。
type指明将指向对象的变量的类型。这必须与类名相匹配或是一个超类或者是一个实现类的接口。记住,变量的名由id属性来指定。
beanName赋予bean一个名字,您应该在Beans的实例化方法中提供。它允许您给出type和一个beanName,并省略类属性。
  

  三、jsp:setProperty Action

  语法:

<jsp:setProperty
name="beanInstanceName"
{
 property="*" | property="propertyName" [ param="parameterName" ] | property="propertyName" value="{string | <%= expression %>}"
}
/>

  在前面我们就知道了可以使用 jsp:setProperty 来为一个bean的属性赋值。您可以使用两种方式实现它。其一是,在jsp:useBean后(而不是在之内)使用jsp:setProperty:

<jsp:useBean id="myName" ... />
...
<jsp:setProperty name="myName"
property="someProperty" ... />

  在这种方式中,jsp:setProperty 将被执行无论是否已有一个具有相同的id和scope的bean存在。另一种方式是,jsp:setProperty出现在jsp:useBean 元素内,如:

<jsp:useBean id="myName" ... >
...
<jsp:setProperty name="myName" property="someProperty" ... />
</jsp:useBean>

  此种情况下,jsp:setProperty仅在新的对象被实例化时才执行。

  以下是四种jsp:setProperty的可用的属性:

属性用法
name这是一个必选属性。它指出哪一个bean的属性将被设置。jsp:usebean必须出现在jsp:setProperty之前。
property这是一个必选属性。表明您将设置哪一个属性。然而,有一个特殊的情况:如果以"*"为值意味着,所有的名称与bean的属性匹配的request参数都将被传递到相应的属性设置方法。
value这是一个可选属性。它指定被设置的属性的值。字符串的值通过相应的对象或包的标准的valueOf方法将自动的转换为numbers,boolean,Boolean,byte,Byte,char,和Character。例如,boolean或Boolean属性的值“true”将通过Boolean.valueOf方法转化,而,一个int或Integer属性的值“42”将通过Integer.valueOf转化。您不能同时使用value和param属性,但,两个都不用是允许的。
param这是一个可选属性。它指明了bean的属性应该继承的request的参数。如果当前的request没有这样的一个参数,就什麽也不做:系统并不将null传给设置属性的方法。因此,您可以使用bean的缺省值。例如下面的这段程序执行“将numberOfItems属性设置为任意numItems request参数的值,如果有这样的一个request参数,否则什么也不做。”

<jsp:setProperty name="orderBean" property="numberOfItems" param="numItems" />
  

  如果您将value和param同时缺省,这和您将param的名称设为bean的属性名相同一样。您可以通过将name的值设置为”*”和省略value和param来自动的使用与bean的属性相应的request的属性。在这种情况下,服务器将反复的查找可用的属性和request参数来匹配具有相同名字的。

  四、jsp:getProperty Action

  语法:

<jsp:getProperty name="beanInstanceName" property="propertyName" />
 
  这个属性检索出bean的属性的值并将之转化为一个字符串,然后将之插入到输出。它有两个必选属性:name,在之前用jsp:useBean引入的名称,property,必须被插入值的属性。


JSP入门初级教程之预定义变量的使用

  JSP表达式和scriptlets中的代码,提供了8种自动定义的变量,有时称做implicit objects(固有对象)。它们是:request,response,out,session,application,config,pageContext,和 page。下面我们来详细的了解它们。

  request

  与request相联系的是HttpServletRequest类,使您可以得到request的参数(通过getParameter方法),request 的类型(GET,POST,HEAD,等等),和引入的HTTP头(cookies,Referer,等等)。严格来说,request是类ServletRequest的一个子类而不是HttpServletRequest类的,事实上,如果request的协议不是HTTP,那麽它几乎不会工作。

  response

  对客户端的response与HttpServletResponse 相连。请注意,因为输出流是放入缓冲的,所以可以设置HTTP状态码和response头,尽管在标准的servlets中不允许将之发送到客户端。

  out

  这里使用PrintWriter类来发送输出到客户端。然而,为了使response对象有效,可使用一个PrintWrite类的使用缓冲的版本JspWriter。使用session的属性page directive,您可以自己定义缓冲的大小,甚至可以在使用了buffer属性后关闭缓冲。也请注意,out仅用于scriptlets之中,因为JSP表达式自动的放入输出流,所以极少需要明确的声明out。

  session

  应用与request相联系的HttpSession类。因为session是自动创建的,即使没有一个引入的session,这种变量仍可绑定。有一个例外是,如果您用page directive关闭session,再试图使用session时将导致错误(在JSP页面向servlet转换时)。

  application

  使用ServeletContext类,通过使用getServletConfig().getContext()得到。

  config

  是一个ServletConfig类的对象。

  pageContext

  这是JSP中的一个新的类PageContext,用于精练特定服务器的特点时使用,如提高JspWriters的执行效率。如果您通过这个类访问而不是直接的,您的代码将仍然运行在“规则”的JSP /servlet引擎 br>

  page

  在JAVA中不是很有用,它仅仅是用来保存在脚本的语言不是JAVA时的时间。


JSP入门初级教程之JSP指令

<JSP directive mso-hansi-font-family:"">影响servlet 类的整体结构

  <JSP directive mso-hansi-font-family:"">影响servlet 类的整体结构。它常用以下形式:

<%@ directive attribute=”value”%>
  
  而且,您可以将多个属性写在一个语句中:

  <%@ directive attribute1="value1" attribute2="value2" attributeN="valueN" %>

  有两种主要的directive:

  page,允许您做一些类似import classes的事,定义servlet的超类(Superclass),
mso-hansi-font-family:"">等;

  include,允许您将文件插入servlet类中(当JSP文件翻译为servlet时)。

  一、JSP page Directive

  语法:

<%@ page
[ language="java" ]
[ extends="package .class" ]
[ import="{package .class | .*}, ..." ]
[ session="true|false" ]
[ buffer="none|8kb|sizekb" ]
[ autoFlush="true|false" ]
[ isThreadSafe="true|false" ]
[ info="text" ]
[ errorPage="relativeURL" ]
[ contentType="mimeType [ ;charset=characterSet ]" |
"text/html ; charset=ISO-8859-1" ]
[ isErrorPage="true|false" ]

%>

  Page directive mso-hansi-font-family:"">允许您定义一些区分大小写的属性:

  (1)import = “package.class”或 import = “package.class1,..,package.classN”。
mso-hansi-font-family:"">

  您可以定想要import的packages。例如:

<%@ page import="java.util.*" %>

  import属性是这几个属性中唯一一个可以在一个JSP中出现多次的。

  (2)contenType = “MIME=Type” 或contentType=“MIME-Type;charset=Character-Set”mso-hansi-font-family:"">

  它指定输出的MIME类型。缺省为“text/html”。例如:

<%@ page contentType="text/plain" %>"

  在scriptlet中等价于:

<% response.setContentType("text/plain"); %>

  (3)isThreadSafe = “true | false”.如果值为“true”(缺省)表示:将进行普通的servlet处理,多个请求将被一个servlet实例并行处理,在这种情况下,编程人员同步访问多个实例变量。值为“false”时表示:servlet将实现单线程模式(SingleThreadModel),不管请求是顺序提交还是并发出现,都将提供不同的分离的servlet实例。

  (4)session=”true | false”。 如果值为“true”(缺省)表示:预定义变量session(继承HttpSession)应该绑定到一个已存在的session,否则就应该创建一个并将之绑定。值为“false”时表示:将不使用session变量,如果试图使用,将在JSP向servlet转化时出现错误。

  (5)buffer = “sizekb | none”。为JspWriter输出确定缓冲的大小。缺省由服务器而定,但至少要有8kb。

  (6)autoflush=”true | false”。 如果值为“true mso-hansi-font-family:"">”(缺省)表示:当缓冲满时将自动清空,值为“false mso-hansi-font-family:"">”时表示:当缓冲满时递出一个异常,这很少使用。当buffer=”none”是若用false mso-hansi-font-family:"">值是不合法的。

  (7)extends=”package.class”。这将为servlet产生一个超类。请特别谨慎的使用这一功能,因为,服务器也许已经定义了一个。

  (8)info = “message”。定义一个可以通过调用getServletInfo方法得到的串。

  (9)errorPage = “URL”。指定一个JSP mso-hansi-font-family:"">页面来处理任何一个可抛出的但当前页面并未处理的意外错误。

  (10)isErrorPage = “true | false”。指定当前页面是否可以处理来自另一个页面的错误,缺省为“false”。

  (11)language = “java” mso-hansi-font-family:"">。指出以下将使用的语言。不过,不必为这一属性费心,因为,“java mso-hansi-font-family:"">”既是缺省又是唯一合法的选择。

  二JSP include Directive 这种directive 使您可以在JSP转换为servlet时将一个文件包含进来。语法:

<jsp:include page="{relativeURL | <%= expression %>}" flush="true" />mso-hansi-font-family:";mso-font-kerning: 0pt">或
<jsp:include page="{relativeURL | <%= expression %>}" flush="true" >
<jsp:param name="parameterName"
value="{parameterValue | <%=expression %>}" />+
</jsp:include>

  URL mso-hansi-font-family:"">通常相对于指向它的JSP页面,但是,普遍使用相对“URL”,您可以使用一个斜杠“/”作为URL的开始来告知系统URL mso-hansi-font-family:"">相对的Web server的主路径。被包含的文件将以规则的JSP形式来解析,因此,您可以在其中使用静态HTML,scripting elements,directives,和 actions。

  让我们来看一个例子,许多站点在每一个页面上包含一个小型的导航条。它通常出现在页面的顶部或左右侧,并包含在每一个页面里。这用include directive 来实现是很自然的,若用规则的HTML mso-hansi-font-family:"">来把这些语句拷到每一个页面无疑是个梦魇。请看下列代码:

<HTML>
<HEAD>
<TITLE> JSP教程</TITLE>
</HEAD>
<BODY>
<%@ include file="/navbar.html" %>
<!— 本页面的其他部分... -->
</BODY>
</HTML>

  因为文件是在页面被转换时插入的,因此,如果导航条改变了,您需要将所有指向它的JSP mso-hansi-font-family:"">页面全部重新编译一次。如果您的导航条并不常改变这样做无疑是高效的,但是,如果您的被包含文件更改频繁,则建议您使用jsp:include action(后面将谈到)来替代,它在页面被请求时才包含文件。
<%@ directive attribute=”value”%>
  
  而且,您可以将多个属性写在一个语句中:

  <%@ directive attribute1="value1" attribute2="value2" attributeN="valueN" %>

  有两种主要的directive:

  page,允许您做一些类似import classes的事,定义servlet的超类(Superclass),
mso-hansi-font-family:"">等;

  include,允许您将文件插入servlet类中(当JSP文件翻译为servlet时)。

  一、JSP page Directive

  语法:

<%@ page
[ language="java" ]
[ extends="package .class" ]
[ import="{package .class | .*}, ..." ]
[ session="true|false" ]
[ buffer="none|8kb|sizekb" ]
[ autoFlush="true|false" ]
[ isThreadSafe="true|false" ]
[ info="text" ]
[ errorPage="relativeURL" ]
[ contentType="mimeType [ ;charset=characterSet ]" |
"text/html ; charset=ISO-8859-1" ]
[ isErrorPage="true|false" ]

%>

  Page directive mso-hansi-font-family:"">允许您定义一些区分大小写的属性:

  (1)import = “package.class”或 import = “package.class1,..,package.classN”。
mso-hansi-font-family:"">

  您可以定想要import的packages。例如:

<%@ page import="java.util.*" %>

  import属性是这几个属性中唯一一个可以在一个JSP中出现多次的。

  (2)contenType = “MIME=Type” 或contentType=“MIME-Type;charset=Character-Set”mso-hansi-font-family:"">

  它指定输出的MIME类型。缺省为“text/html”。例如:

<%@ page contentType="text/plain" %>"

  在scriptlet中等价于:

<% response.setContentType("text/plain"); %>

  (3)isThreadSafe = “true | false”.如果值为“true”(缺省)表示:将进行普通的servlet处理,多个请求将被一个servlet实例并行处理,在这种情况下,编程人员同步访问多个实例变量。值为“false”时表示:servlet将实现单线程模式(SingleThreadModel),不管请求是顺序提交还是并发出现,都将提供不同的分离的servlet实例。

  (4)session=”true | false”。 如果值为“true”(缺省)表示:预定义变量session(继承HttpSession)应该绑定到一个已存在的session,否则就应该创建一个并将之绑定。值为“false”时表示:将不使用session变量,如果试图使用,将在JSP向servlet转化时出现错误。

  (5)buffer = “sizekb | none”。为JspWriter输出确定缓冲的大小。缺省由服务器而定,但至少要有8kb。

  (6)autoflush=”true | false”。 如果值为“true mso-hansi-font-family:"">”(缺省)表示:当缓冲满时将自动清空,值为“false mso-hansi-font-family:"">”时表示:当缓冲满时递出一个异常,这很少使用。当buffer=”none”是若用false mso-hansi-font-family:"">值是不合法的。

  (7)extends=”package.class”。这将为servlet产生一个超类。请特别谨慎的使用这一功能,因为,服务器也许已经定义了一个。

  (8)info = “message”。定义一个可以通过调用getServletInfo方法得到的串。

  (9)errorPage = “URL”。指定一个JSP mso-hansi-font-family:"">页面来处理任何一个可抛出的但当前页面并未处理的意外错误。

  (10)isErrorPage = “true | false”。指定当前页面是否可以处理来自另一个页面的错误,缺省为“false”。

  (11)language = “java” mso-hansi-font-family:"">。指出以下将使用的语言。不过,不必为这一属性费心,因为,“java mso-hansi-font-family:"">”既是缺省又是唯一合法的选择。

  二JSP include Directive 这种directive 使您可以在JSP转换为servlet时将一个文件包含进来。语法:

<jsp:include page="{relativeURL | <%= expression %>}" flush="true" />mso-hansi-font-family:";mso-font-kerning: 0pt">或
<jsp:include page="{relativeURL | <%= expression %>}" flush="true" >
<jsp:param name="parameterName"
value="{parameterValue | <%=expression %>}" />+
</jsp:include>

  URL mso-hansi-font-family:"">通常相对于指向它的JSP页面,但是,普遍使用相对“URL”,您可以使用一个斜杠“/”作为URL的开始来告知系统URL mso-hansi-font-family:"">相对的Web server的主路径。被包含的文件将以规则的JSP形式来解析,因此,您可以在其中使用静态HTML,scripting elements,directives,和 actions。

  让我们来看一个例子,许多站点在每一个页面上包含一个小型的导航条。它通常出现在页面的顶部或左右侧,并包含在每一个页面里。这用include directive 来实现是很自然的,若用规则的HTML mso-hansi-font-family:"">来把这些语句拷到每一个页面无疑是个梦魇。请看下列代码:

<HTML>
<HEAD>
<TITLE> JSP教程</TITLE>
</HEAD>
<BODY>
<%@ include file="/navbar.html" %>
<!— 本页面的其他部分... -->
</BODY>
</HTML>

  因为文件是在页面被转换时插入的,因此,如果导航条改变了,您需要将所有指向它的JSP mso-hansi-font-family:"">页面全部重新编译一次。如果您的导航条并不常改变这样做无疑是高效的,但是,如果您的被包含文件更改频繁,则建议您使用jsp:include action(后面将谈到)来替代,它在页面被请求时才包含文件。

JSP入门初级教程之JSP概述

  JSP(IAVA SERVER PAGES)是由Sun 公司在java语言上开发出来的一种动态网页制作技术,其可使您可以将网页中的动态部分和静态的HTML相分离。您可以使用平常得心应手的工具并按照平常的方式来书写HTML语句。然后,将动态部分用特殊的标记嵌入即可,这些标记常常以“<%”开始并以“%>”结束。例如,这儿有一个JSP页面:

<html>

<head><title>jsp教程</title></head>

<body>

<I><%out.println(“hello world”);%></I>

</body></html>

  它将输出“hello world”。

  通常,您要将文件以“.jsp”为扩展名,并将它放置到任何您可以放置普通WEB页面的路径下。尽管JSP文件看起来更象是HTML文件而不是Servlet文件,但,事实上,它恰恰将转换为Servlet文件,其中的静态HTML仅仅用来输出Servlet服务方法返回的信息。如果JSP pages 已经被转换为Servlet且Servlet 被编译进而被装载(在第一次被Request时),当您再次Request 此JSP页面时,将察觉不到一瞬的延迟。也请留意这个现象,一些Web Servers允许您为它定义别名,从而,好象一个URL是指向一个HTML,但事实上它指向的是一个Servlet 或JSP pages.

  构造一个JSP page,除了可内嵌的规则的HTML,还有三类主要的JSP元素:Scripting elements,Directives,和 Actions.使用Scripting elements您可以定义最终转换为Servlet的部分,Directives 使您可以控制这个Servlet的整体结构,而Actions使您可以指定可重用的已有组件,另外,还可控制JSP引擎的运行。为了简化Scripting elements,您可以在某一段上利用一些预定义的变量,如request。

  本教程式是以JSP1.1版本进行讲解的。其语法概括如下表,其详细使用在随后的课程中详细讲解.

JSP 元素语法解释JSP Expression<%= 表达式 %>Expression 用于计算并用于输出。
<jsp:expression>表达式</jsp:expression>,可使用的预定义的变量有request, response, out, session, application, config, and pageContext(在Sriptlets中也可使用)。JSP Scriptlet<% 代码 %>
插入用于服务的代码。
<jsp:scriptlet>代码</jsp:scriptlet>JSP Declaration<!% 代码 %>属于Servlet部分的代码但并不是服务方法。
<jsp:declaration>代码</jsp:declaration>JSP page Directive<%@ page att=”val” %>指向Servlet引擎的路径。
<jsp:directive.page att="val"/>. 以下是其合法的属性(缺省值加粗):

import="package.class"
contentType="MIME-Type"
isThreadSafe="true|false"
session="true|false"
buffer="sizekb|none"
autoflush="true|false"
extends="package.class"
info="message"
errorPage="url"
isErrorPage="true|false"
language="java"
JSP include Directive<%@ include file =”URL” %>当JSP page被翻译成Servlet 时将被包含进去的本地系统上的文件。
<jsp:directive.include file=”URL”/> 这个URL必须是相对的。当页面被请求时才用 “jsp:include action”调入。JSP 注释<%-- 注释--%>当JSP 转换为Servlet 时将被忽略。
<-- 注释 -->The JSP:include Action <jsp:include page=”relative URL” flush=”true”/>在页面被请求(Requested)时调入文件。
如果您想要在页面被转化(Translated)时将文件包含进来,则,请使用上面所提到的directive来代替。警告:在一些服务器上(Servers),被包含的文件只能是HTML或JSP,一般以文件的后缀名来判定。The jsp:useBean Action<jsp:useBean att=val*/>或<jsp:useBean att=val*>
…..
</jsp:useBean>寻找或生成一个Java Bean.
可能的属性是:

id="name"
scope="page|request|session|application"
class="package.class"
type="package.class"
beanName="package.class"
The jsp:setProperty Action<jsp:setProperty att=val*/>设置bean的属性,通过明确的指定或使用request得到的参数。
合法的属性:

name="beanName"
property="propertyName|*"
param="parameterName"
value="val”The jsp:getProperty Action<jsp:getProperty name=”propertyName” value=”val”/>检索并输出bean的属性。The jsp:forward Action
<jsp:forward page=”relative URL”/>向前请求(request)另一个页面。The jsp:plugin Action<jsp:plugin attribute=”value”*>
</jsp:plugin>生成特定的浏览器的OBJECT 或EMBED标签,用来明确运行Applet所 使用的JAVA插件(plugin)。

常用的五个组合键


winkey+d :

这是高手最常用的第一快捷组合键。这个快捷键组合可以将桌面上的所有窗口瞬间最小化,无论是聊天的窗口还是游戏的窗口……只要再次按下这个组合键,刚才的所有窗口都回来了,而且激活的也正是你最小化之前在使用的窗口!

winkey+f :
不用再去移动鼠标点“开始→搜索→文件和文件夹”了,在任何状态下,只要一按winkey+f就会弹出搜索窗口。

winkey+r :
在我们的文章中,你经常会看到这样的操作提示:“点击‘开始→运行’,打开‘运行’对话框……”。其实,还有一个更简单的办法,就是按winkey + r!

alt + tab :
如果打开的窗口太多,这个组合键就非常有用了,它可以在一个窗口中显示当前打开的所有窗口的名称和图标●,选中自己希望要打开的窗口,松开这个组合键就可以了。而alt+tab+shift键则可以反向显示当前打开的窗口。

winkey+e :
当你需要打开资源管理器找文件的时候,这个快捷键会让你感觉非常“爽”!再也不用腾出一只手去摸鼠标了!


小提示:
winkey指的是键盘上刻有windows徽标的键●。winkey主要出现在104键和107键的键盘中。104键盘又称win95键盘,这种键盘在原来101键盘的左右两边、ctrl和alt键之间增加了两个windwos键和一个属性关联键。107键盘又称为win98键盘,比104键多了睡眠、唤醒、开机等电源管理键,这3个键大部分位于键盘的右上方。

展开阅读全文

没有更多推荐了,返回首页