JSP 1.X编码规范

JSP编码规范!!!!! JSP的编码规范~~!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 立即下载
JSP 1.X编码规范
       由于JavaServer Page (JSP )技术广泛应用于WEB 应用程序,如同许多Java 程序员一样,许多JSP 程序员和WEB 应用开发者在开发和维护这些应用程序时面临一些难以抉择的问题:“我们该如何编写更易于阅读、编写和维护的JSP 代码”。
 
1.         为什么需要编码规范
编码规范对于程序员和WEB 内容开发者来说非常重要,原因有数个:
1 )编码规范可以提高软件的可读性
2 )编码规范可以减少培训工作量
3 )编码规范可以推动组织或团队的标准化
 
2.         文件命名和存放位置
文件命名能够让一些工具和WEB 容器识别文件的类型和采用相应处理方法。下表列出了建议使用的文件后缀名和存放位置。
 
文件类型
文件后缀
建议存放位置
JSP technology
.jsp
<context root>/<subsystem path>/
JSP fragment
.jsp
<context root>/<subsystem path>/
.jspf
<context root> /WEB-INF/jspf/ <subsystem path>/
cascading style sheet
.css
<context root> /css/
JavaScript technology
.js
<context root> /js/
HTML page
.html
<context root>/<subsystem path>/
web resource
.gif, .jpg , etc.
<context root> /images/
tag library descriptor
.tld
<context root> /WEB-INF/tld/
 
对以上表格需要说明的是:
第一, <context root> 是 WEB 应用程序上下文的根目录(或 .war 文件里的根目录)。
第二, <subsystem path> 用于提供动态和静态 WEB 页面内容的准确的逻辑分类,对于小型的 WEB 应用程序,它可能是一个空字符串。
第三,我们将可能包含在其他 JSP 页面中的 JSP 页面称为 JSP fragment 。注意,在 JSP 2.0 中,“ JSP fragment ”被术语“ JSP segment ” 替换。 JSP fragment 文件可以用 .jsp 和 .jspf 作为文件名后缀,而且应该被放在 /WEB-INF/jspf 文件目录中,或者和其它静态内容放在一起。因为不是完整的页面, JSP fragment 文件应该使用 .jspf 作为文件名后缀,并且应该放在 /WEB-INF/jspf 文件目录中。
第四,尽管 JSP 规范认为 .jspf 和 .jsp 都可以作为 JSP fragment 文件名后缀,但是我们建议使用 .jspf ,就如 .jsf 被 JavaServer Faces 规范所采用。
最后,将标签库描述符文件(tag library descriptor )和其他非公开的内容放在 /WEB-INF/ 中或其下的子目录中通常是好的习惯。在这种情况下,这些内容对于客户端是访问不到的和不可见的,因为 WEB 容器不会对这个目录下的文件提供访问服务。
 
在部署描述符文件( web.xml )中 welcome-file 元素中声明首页文件( welcome file ),如果是动态内容,其文件名应该是 index.jsp ,如果是静态内容就应该用 index.html 。
 
一旦我们要将 JSP 文件国际化,我们建议将 JSP 页面分组分别存放在各自的本地目录中。例如, US English 版的 index.jsp 应该以 /en_US/index.jsp 方式保存,同样日语版的 index.jsp 文件应存为 /ja_JP/index.jsp 。 Java Tutorial 一书提供了通常情况下如何将 Java 代码国际化的方法的信息, Designing Enterprise Applications with the J2EE Platform 一书也有WEB 应用程序国际化的内容。
 
3.         文件组织
有良好组织结构的源码文件不仅易读,而且在文件中也能很快就能找到需要的信息。在这一部分,我们将介绍JSP 文件和标签库描述符(tag library descriptor )文件的组织结构。
 
3.1          JSP 文件/JSP Fragment 文件
一个JSP 文件包含按列出顺序排列的以下部分:
1)  开头注释
2) JSP 页面指令(JSP Page Directive )
3)  可选的标签库(tag library )指令
4)  可选的JSP 声明
5) HTML 和JSP 代码
 
3.1.1.       开头注释
一个JSP 文件或片断(fragment )文件以服务端注释开始:
 
<%--
 - Author(s):
 - Date:
 - Copyright Notice:
 - @(#)
 - Description:
 --%>
 
由于在JSP 页面翻译转换时,这种注释被删除,所以它仅在服务端可见。注释中有作者、日期、版权声明、标志符和对WEB 开发者的该JSP 页面的描述信息。字符组合“@(#) ”是用来为某种特定的程序识别标志符的开始位置的。虽然这类程序很少被用到,但是这个字符串没有什么坏处。另外,某些时候这个字符串后被一些控制程序自动添加“$Id$ ”作为标志信息。描述信息部分提供了JSP 页面的用途的简要信息。这部分不能超过一段。
在某些情况下,为了证实真实性和法律的用途,开头部分注释需要在翻译转换并产生结果后保留并传送到客户端。将开头注释分为两部份就可以实现这个要求;第一部分是客户端注释:
 
 
<!--
 - Author(s):
 - Date:
 - Copyright Notice:
 -->
 
第二部分是比较简短的服务端注释:
 
<%--
 - @(#)
 - Description:
 --%>
 
3.1.2.       JSP 页面指令(JSP Page Directive )
JSP 页面指令定义了JSP 页面在翻译转换时需要的一些属性。JSP 规范没有强制约束在一个JSP 页面中可以定义多少个JSP 页面指令。于是下面两个代码例子是等同的(除了第一个例子在结果输出时会多两个空行):
 
例1 :
<%@ page session="false" %>
<%@ page import="java.util.*" %>
<%@ page errorPage="/common/errorPage.jsp" %>
 
任何指令的长度超过JSP 页面的通常的宽度,例如JSP 页面指令,那么这个指令应该分成多行:
 
例2 :
<%@ page    session="false"
            import="java.util.*"
            errorPage="/common/errorPage.jsp"
%>
 
通常情况下,例2 是比较好的定义JSP 页面指令的方法。一个例外,当需要引入多个java 包到JSP 页面时,导致import 属性很长:
 
<%@ page    session="false"
            import="java.util.*,java.text.*,
                    com.mycorp.myapp.taglib.*,
                    com.mycorp.myapp.sql.*, ..."
...
%>
 
这种情况下,首选的做法是将指令做如下拆分:
 
 
<%-- all attributes except import ones --%>
<%@ page
...
%>
<%-- import attributes start here --%>
<%@ page import="java.util.*" %>
<%@ page import="java.text.*" %>
 
注意:通常使用import 命令要遵循Java 编码规范。例如,当同一个包中的少于(含)3 个类被引用,import 应该对每个类逐个引入,而不是引入整个包。超过3 个类时,由开发者来确定是每个类逐个引入还是使用“.* ”符号来引入整个包。前者能够帮助更容易的确定外部类,尤其是当你试图查找一个有bug 的类,或想理解JSP 页面是如何和Java 代码是如何交互的。例如,在不了解如下所示引入的包的情况下,WEB 开发者将不得不将这些包查个遍才能找到某个用户类:
 
<%@ page import="com.mycorp.bank.savings.*" %>
<%@ page import="com.thirdpartycorp.cashmanagement.*" %>
<%@ page import="com.mycorp.bank.foreignexchange.*" %>
...
 
在这种情况下,JSP页面虽然简洁,但是就很难定位类。通常情况下,如果一个JSP页面有太多的import指令,那么页面中就很可能包含较多的Java代码。比较好的选择就是尽量使用JSP标签(本文后面会有说明)。
 
3.1.3.       可选的标签库(Tag Library )指令
标签库指令声明了JSP 页面中使用的用户标签库。一行使用一个指令声明。在JSP 页面中多个标签库指令应该堆叠在一起放在同一位置:
 
<%@ taglib uri="URI1" prefix="tagPrefix1" %>
<%@ taglib uri="URI2" prefix="tagPrefix2" %>
...
 
就如page指令一样,如果标签库指令的长度超过JSP页面的标准长度(80个字符),就应该拆分多行:
 
<%@ taglib
    uri="URI2"
    prefix="tagPrefix2"
%>
 
只有要用到的标签库才能被声明。
从JSP 2.0之后,JSP标准标签库(JSTL)被强烈推荐应用于WEB应用程序中以帮助减少页面中JSP Scriptlets的使用。通常,使用JSTL的页面更易于阅读和维护。
 
3.1.4.       可选的JSP 声明
“JSP声明”声明了JSP页面拥有的方法和变量。这些方法和变量与Java编程语言中声明的方法和变量没有不同,因此,相关的编码规范也同样被遵循。声明首选被包含在一个<%! ... %>JSP声明块中,并且把这些声明集中在JSP页面中的一个区域。这里有一个例子:
 
分散的声明块
首选的声明块
    <%! private int hitCount; %>
    <%! private Date today; %>
    ...
    <%! public int getHitCount() {
            return hitCount;
        }
    %>
    <%!
        private int hitCount;
        private Date today;
   
        public int getHitCount() {
            return hitCount;
        }
    %>
 
3.1.5.       HTML 和JSP 代码
这一部分包括JSP 页面的HTML 体和JSP 代码,如:JSP 表达式、Scriptlets 和JavaBean 命令。
 
3.2          标签库描述符
标签库描述符(TLD )文件必须用正确的XML 声明和正确的DTD 命令开始。例如,一个JSP 1.2 TLD 文件必须以如下开始:
 
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
    PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
    "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
 
之后紧跟的是服务端注释,其中列出了作者、日期、版权、标志信息和对于标签库的简短说明:
 
<!--
 - Author(s):
 - Date:
 - Copyright Notice:
 - @(#)
 - Description:
 -->
 
注释中各个元素的使用规则和指导方法和JSP/JSP fragment文件中的注释定义的一样。
 
这个文件的剩余部分以下部分,在文件中的顺序和列出顺序相同:
l         可选 的标签库校验器( tag library validator )声明
l         可选的事件侦听器(event listener)声明
l         一个或多个可用的标签的声明
 
这里还建议在TLD 文件的元素下增加以下可选的子元素。这些子元素给标签的设计者提供了书写关于标签文件的行为和附加信息的文档的地方,并且可以把这些信息提供给WEB 组件开发者。
TLD 元素
JSP 1.2 推荐的子元素
JSP 1.1 推荐的子元素
attribute (JSP 1.2)
description
 
init-param (JSP 1.2)
description
 
tag
display-name, description, example
name, info
taglib
uri, display-name, description
uri, info
validator (JSP 1.2)
description
 
variable (JSP 1.2)
description
 
 
4.         缩进排版
缩进的地方应该填入空格符,Tab 符在不同的编辑器中表示不同的字符间隔,因此在JSP 页面中不能用于缩进排版。除非受特定的IDE 工具限制,通常情况下一个缩进单位代表4 个空格符。下面是个例子:
 
<myTagLib:forEach var="client" items="${clients}">
    <myTagLib:mail value="${client}" />
</myTagLib:forEach>
 
在连续缩进的情况下,后面的行要对齐前面的行的适当的位置。连续缩进是指多个连续的标准缩进(即多个4个空格符):
 
<%@ page    attribute1="value1"
            attribute2="value2"
            ...
            attributeN="valueN"
%>
 
 
4.1          脚本元素的缩进
当一个JSP 脚本元素(包括声明、Scriptlet 、表达式)超过一行,我们接受的缩进规范将作用于这个元素的体部分。体部分开始于和元素开始标志 <%= 同一行,或开始标志 <% 之后新的一行。体部分结束于单独一行的元素封闭标志(%> )之前。例如:
 
 
<%= (Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
        =Calendar.SUNDAY) ?
    "Sleep in" :
    "Go to work"
%>
 
不包含脚本元素开始标志和结束标志的元素体部分的行都以一个标准缩进单位打头(如上例 所示部分),这样使脚本元素体能够同JSP 页面的其他部分清晰地区分开来。
 
4.2          含有JSP 、HTML 、Java 的混合缩进排版
混有Java 脚本代码和模板文本(HTML )的混合缩进排版,对于降低领会理解JSP 源文件的难度,混合缩进排版是有必要的。这是因为传统的标准缩进排版使阅读JSP 源文件比较困难。作为一般的惯例,对一个元素内部引入的另一个元素加上一个标准缩进单位。注意这种方法将改变最终输出到客户端用于显示的结果的缩进排版格式。然而这些附加的缩进通常会被浏览器忽略,并且不会对显示在浏览器中的输出结果造成任何影响。例如,在 <table> 标签前加更多的空格字符不会改变表格的位置。所以,下面使用了缩进排版的例子:
    <table>
        <% if ( tableHeaderRequired ) { %>
            <tr>
                <th>Last Name</th>
                <th>First Name</th>
            </tr>
        <% } %>
        <c:forEach var="customer" items="${customers}">
            <tr>
                <td><c:out value="${customer.lastName}"/></td>
                <td><c:out value="${customer.firstName}"/></td>
            </tr>
        </c:forEach>
    </table>
 
就要比以下的例子:
    <table>
        <% if ( tableHeaderRequired ) { %>
        <tr>
            <th>Last Name</th>
            <th>First Name</th>
        </tr>
        <% } %>
        <c:forEach var="customer" items="${customers}">
        <tr>
            <td><c:out value="${customer.lastName}"/></td>
            <td><c:out value="${customer.firstName}"/></td>
        </tr>
        </c:forEach>
</table>
 
可读性要强一些。
 
5.         注释
注释被用来简要描述附近代码的附加信息或用途。这里我们将看到JSP文件中的两种注释:JSP(服务端)注释和客户端注释。
 
5.1          JSP 注释
JSP 注释(也称为服务端注释)只能在服务端可见(也就是说,这类注释不会被发送到客户端)。纯JSP注释要优于带有脚本语言注释的JSP注释,因为前者不依赖于相关的脚本语言,并且易于迁移至JSP 2.0风格的页面。下面的表格对此做了说明:
 
行数
带有脚本语言注释的JSP 脚本
纯JSP 注释
单行
    <% /** ... */ %>
    <% /* ... */ %>
    <% // ... %>   
    <%-- ... --%>
多行
    <%
    /*
     *
    ...
     *
     */
    %>
 
    <%--
      -
     ...
      -
      -- %>
 
    <%
    //
    //
    ...
    //
    %>
 
 
5.2       客户端注释
客户端注释(<!-- ... -->)能够用于对发往客户端的响应信息加以注释。其中不能包含服务端应用程序的行为和内部架构的相关信息和生成响应的代码。
通常客户端注释的使用是不鼓励的,因为客户/用户不需要也不会直接阅读这些注释来解释收到的响应信息。一个例外是为了确认真实性和法律性用途,例如上面所述的标志性信息和版权信息。另外一个例外就是HTML作者使用少量HTML注释来说明HTML文档的结构。例如:
 
<!-- toolbar section -->
    ...
<!-- left-hand side navigation bar -->
    ...
<!-- main body -->
    ...
<!-- footer -->
    ...
 
5.3       多行注释块
多行注释块,无论是JSP注释还是客户端注释,每行前都用“-”修饰。在XML规范中,双破折号“--”不允许在XML注释块中使用。于是,为了兼容这个规范并且保持一致性,在多行注释块中双破折号“--”不能用来修饰其中的注释行。下面的表格以客户端注释来说明这个问题:
首选格式
非XML兼容格式
    <!--
      - line 1
      - line 2
    ...
      -->
    <!--
      -- line 1
      -- line 2
    ...
      -->
 
6.         JSP 声明
按照Java编码规范,相同类型的变量的声明应该放在不同的行中:
 
不推荐的
推荐的
   <%! private int x, y; %>
    <%! private int x; %>
    <%! private int y; %>
 
JavaBean 组件不应该用JSP声明来声明和生成实例,而应该使用<jsp:userBean>这个JSP动作标签。
    通常使用JSP声明来声明变量是不推荐使用的,因为这将导致脚本语言的使用,将业务逻辑和Java代码混入本应设计用于表现用途的JSP页面。
 
7.         JSP Scriptlets
若可能,一旦标签库提供了相同的功能就尽量避免使用JSP Scriptlets。这样是JSP页面更易于阅读和维护,有助于将业务逻辑从表现逻辑中分离出来,并且使这样的JSP页面更易于迁移至JSP 2.0风格的页面(JSP 2.0支持但不鼓励使用Scriptlets)。在下面的例子中,customers的数据类型不同,那么就一定有不同的Scriptlet的写法:
 
customers 是Customers数组时
 
    <table>
        <% for ( int i=0; i<customers.length; i++ ) { %>
            <tr>
                <td><%= customers[i].getLastName() %></td>
                <td><%= customers[i].getFirstName() %></td>
            </tr>
        <% } %>
    </table>
 
customers 是Enumeration时
 
    <table>
        <% for ( Enumeration e = customers.elements();
                e.hasMoreElements(); ) {
                Customer customer = (Customer)e.nextElement();
        %>
            <tr>
                <td><%= customer.getLastName() %></td>
                <td><%= customer.getFirstName() %></td>
            </tr>
        <% } %>
    </table>
 
然而,如果使用通用标签库,对使用不同类型的customers更有灵活性。例如:在JSP标准标签库(JSTL)中,下面一段JSP代码支持数组和Enumeration类型的customers:
 
    <table>
        <c:forEach var="customer" items="${customers}">
            <tr>
                <td><c:out value="${customer.lastName}"/></td>
                <td><c:out value="${customer.firstName}"/></td>
            </tr>
        </c:forEach>
    </table>
 
在采用模型-视图-控制器(MVC)设计模式来降低表现层同业务逻辑的耦合的思想中,JSP Scriptlets不应该用来编写业务逻辑。如果有必要的话,JSP Scriptlets可以用来将处理用户请求的返回数据(也称为“值对象(value objects)”)转换成客户端需要的格式。即便如此,用前端控制器或用户自定义标签来处理数据格式转换要更好一些。例如,下面的代码直接从数据库中取出客户的姓名并且显示在客户端:
 
<%
    // NOT RECOMMENDED TO BE DONE AS A SCRIPTLET!
 
    Connection conn = null;
    try {
        // Get connection
        InitialContext ctx = new InitialContext();
        DataSource ds = (DataSource)ctx.lookup("customerDS");
        conn = ds.getConnection();
 
        // Get customer names
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT name FROM customer");
 
        // Display names
        while ( rs.next() ) {
            out.println( rs.getString("name") + "<br>");
        }
    } catch (SQLException e) {
        out.println("Could not retrieve customer names:" + e);
    } finally {
        if ( conn != null )
            conn.close();
    }
%>
 
下面一段JSP代码就要优于上面的代码,因为它将和数据库的交互委托给了用户自定义标签myTags:dataSource,这个标签封装并隐藏了与数据库相关的代码:
 
<myTags:dataSource
    name="customerDS"
    table="customer"
    columns="name"
    var="result" />
<c:forEach var="row" items="${result.rows}">
    <c:out value="${row.name}" />
    <br />
</c:forEach>
 
result 是自定义标签myTags:dataSource生成的用来保存从客户数据库取出的客户姓名的变量。JSP代码能够根据客户的需要动态的生成不同的输出信息(HTML、XML、WML),而不会影响后端的代码(例如:dataSource标签)。比较好的选择是将从数据库提取数据并且将结果通过request范围(request-scoped)的属性(attribute)提供给JSP页面这些工作委托给前端控制器Servlet。相关的例子请参看Java BluePrints的企业部分。
 
小结:
l         理想情况下,在JSP页面中JSP Scriptlet应该是不存在的,因此,JSP页面是与脚本语言无关的,要避免的业务逻辑在JSP页面中实现。
l         上面如果不可能做到,要使用值对象(JavaBean组件)在服务端传递数据,用JSP Scriptlet来转换值对象的格式输出到客户端。
l         若有可能在服务端尽量使用自定义标签(标签处理器)来处理数据。
 
8.         JSP 表达式
同JSP Scriptlet一样,JSP表达式应该谨慎使用。让我们来看看以下完成相同任务的三个例子:
 
例1 (直接使用Java代码):
<%= myBean.getName() %>
 
例2 (使用JSP标签):
<jsp:getProperty name="myBean" property="name" />
 
例3 (使用JSTL标签):
    <c:out value="${myBean.name}" />
 
例1假设脚本变量myBean已经被声明。另外两个例子假设myBean是个在有效范围内的属性(attribute),能够被PageContext.findAttribute找得到。第二个例子也假设myBean由页面中的<jsp:useBean>引入。
在以上三个例子中,JSTL的例子是首选的。这种方式的代码同使用的JSP表达式的几乎一样简短,而且易于阅读更易于维护,它不依赖Java Scriptlet(Java Scriptlet需要WEB开发者对此语言和API调用熟悉)。此外,这样也使得将这些页面更易于迁移至JSP 2.0风格编程,在JSP 2.0风格下简单地在模板文本中输入${myBean.name}就可以实现以上相同的功能。应该注意的是JSTL的例子在从页面上下文PageContext取得myBean的值同从本地的Java脚本变量中取值确实略微有些不同。
最后,JSP表达式要优于同样作用的JSP Scriptlet,后者依赖于相关脚本语言的语法。例如:
 
    <%= x %>
就要优于
    <% out.print( x ); %>
 
9.         空白(White Space )
空 白 产生的缩进排版美化的JSP代码可以减少理解和维护的工作量。特别是在JSP文件的多个位置需要插入空行和空格。
 
9.1          空行(Blank Lines)
如果不会对输出造成不想要的影响,空行可以谨慎地用来提高JSP的易读性。下面的例子,在HTML标签<pre>块内部两个JSP表达式之间插入了一个空行,将导致输出的HTML在客户端浏览器上有多余的一行。然而如果加在<pre>块外部,在浏览器上就不会有这种效果。
 
JSP 语句
输出到客户端浏览器上的HTML效果
    <pre>
    <%= customer.getFirstName() %>
    <%= customer.getLastName() %>
    </pre>
    Joe
    Block
    <pre>
    <%= customer.getFirstName() %>
 
    <%= customer.getLastName() %>
    </pre>
 
   
    Joe
        
    Block
    <%= customer.getFirstName() %>
 
    <%= customer.getLastName() %>
    Joe Block
 
 
9.2       空格(Blank Spaces)
在JSP标签和它的内容之间应该加入一个空格(如)。例如:下面
    <%= customer.getName() %>
就要优于
    <%=customer.getName()%>
 
在JSP注释标签和注释内容之间应该有空格符分隔:
<%--
 - a multi-line comment broken into pieces, each of which
 - occupying a single line.
 --%>
<%-- a short comment --%>
 
 
10.     命名规范
使用命名规范使项目中WEB组件元素更容易识别、分类和整理。在这一节我们将看到JSP的命名规范。
 
10.1       JSP 文件命名(JSP Names )
JSP 文件名应该用小写字母开头。名字可以包含多个单词,之后每个单词的首字母大写。JSP文件名可以是简单的一个名词或一个短语。应该避免仅有一个动词的JSP文件名,因为这样的文件名不能为开发者提供充足的信息。例如:
perform.jsp
就不如
performLogin.jsp
清晰。
 
在动词作为JSP文件名的情况下,应该使用动词的一般现在时形式,因为它暗示了作为后端处理的动作:
showAccountDetails.jsp
要优于
showingAccountDetails.jsp
 
10.2       标签名(Tag Names)
下面显示了标签处理器和相关的类的命名规范:
 
描述
类名
XXX tag extra info (extending from javax.servlet.jsp.tagext.TagExtraInfo )
XXXTEI
XXX tag library validator (extending from javax.servlet.jsp.tagext.TagLibraryValidator )
XXXTLV
XXX tag handler interface (extending from javax.servlet.jsp.tagext.Tag/IterationTag/BodyTag )
XXXTag
XXX tag handler implementation
XXXTag
 
另外,标签命名不能违反Java编码规范中类和接口的命名规范。
为了将标签相关的类与其他的类区分开来,这些类所属包的名称后缀应使用tags或taglib。例如:
com.mycorp.myapp.tags.XXXTag
 
 
 
10.3       标签前缀名(Tag Prefix Names )
标签前缀名应该是简短而有意义的标题形式的名词,并且首字母小写。标签前缀名不应该包含非字母字符。以下是一些示例:
例
OK?
mytaglib
no
myTagLib
yes
MyTagLib
no
MyTagLib1
no
My_Tag_Lib
no
My$Tag$Lib
no
 
 
11.     XML 语法下的JSP 页面(JSP Pages in XML Syntax )
JSP 提供了两种不同的语法:一种是写JSP页面的“标准语法”,一种是写作为XML文档的JSP页面的“XML语法”。用标准语法写的JSP页面被称为“JSP 页面(JSP pages)”。用XML语法写的JSP页面被称为“JSP文档(JSP documents)”本文主要讲述的是JSP页面,但是也有许多应用于JSP文档的概念。因为XML被普遍采用,JSP文档的使用也被期望不断增加,因此JSP 2.0规范将引入更友好的XML语法。
应该注意到使用XML语法编写JSP页面和JSP页面的XML视图是有区别的而且经常也容易混淆。页面编写者可以使用标准语法或XML语法来编写JSP页面。然后容器将JSP页面翻译成暴露在标签库校验器下的XML视图。
 
11.1       JSP 文档结构
JSP 文档有以下基本结构:
 
    <? xml version="1.0" ?>
    <!--
      - Author(s):
      - Date:
      - Copyright Notice:
      - @(#)
      - Description:
      -->
    <jsp:root   xmlns:jsp="http://java.sun.com/JSP/Page"
                xmlns:prefix1="URI-for-taglib1"
                xmlns:prefix2="URI-for-taglib2"
                version="1.2">
        JSP Document ...
    </jsp:root>
 
第一行是可选的定义该页面是一个XML文档的XML序言。序言之后是该文档的注释。<jsp:root>元素定义了这是一个JSP文档,并且作为root元素出现。必须引入jsp这个名称空间,所有的标签库也必须使用这个root元素引入。属性version是必要的,用来指明使用的JSP规范的版本。实际的内容作为<jsp:root>的子元素出现。标准的XML缩进排版规则应该在文档中继续沿用,用4个空格作为一个缩进单位。
JSP 文档必须是一个具有良好格式的XML文档,因此例如<% %>之类的元素就必须使用等效的XML元素,例如<jsp:scriptlet />。细节请查看JSP规范。
 
11.2   XML 注释(XML Comments)
JSP 规范在规定XML风格(XML-style)的注释输出时是否会被去掉的问题上不太明确,于是如果要求注释输出到客户端,为了保证这一点,注释内容就要如以下所示包在<jsp:text>节点里面:
 
    ...
    <jsp:text><![CDATA[
        <!--
          - Multiline comment
          - to be sent to client.
          -->
    ]]></jsp:text>
    ...
 
11.3   JSP 文档中的Java代码
当要在声明、Scriptlet和表达式中写Java代码时,若有必要确保这些Java代码不会破坏文档结构,就应该使用CDATA元素。
 
    ...
    <jsp:scriptlet>
        for( int level = 0; level &lt; 3; level++ ) {
    </jsp:scriptlet>
    <tr>
        <td>
            <jsp:expression><![CDATA[
                "<h" + level + ">Text</h" + level + ">"
            ]]></jsp:expression>
        </td>
    </tr>
    <jsp:scriptlet>
        }
    </jsp:scriptlet>
    ...
跟JSP标准语法中的缩进方式不一样,XML缩进应该被遵守,而不管每个元素的内容是什么。
 
12.     编程惯例
一般来说,由于以下原因,避免在JSP页面中写Java代码(声明、Scriptlet和表达式):
l         直到JSP页面部署,其中的Java代码的语法错误是检测不出来的。另一方面,在标签库和Servlet中的错误在部署前就能发现。
l         JSP 页面中的Java代码比较难于调试。
l         JSP 页面中的Java代码比较难于维护,尤其是哪些不是Java专业者的页面作者。
l         不要将复杂的业务逻辑和表现逻辑混在一起已广为接受。JSP页面主要用于表现逻辑。
l         包含有Java代码、HTML和其他脚本指令的代码可能难于阅读。
l         JSP 2.0 倾向于使用更简单的表达式语言而不推荐使用Scriptlet。如果在你的JSP页面中没有使用Java代码,就很容易将你的页面迁移至JSP 2.0方式编程。
更多指导思想和细节请参看Java BluePrints的企业部分。
 
12.1       JavaBean 组件的初始化(JavaBeans Component Initialization)
JSP 提供了一个方便的元素来初始化属性描述符确定的JavaBean组件的所有属性。例如:
 
<jsp:setProperty name="bankClient" property="*"/>
 
但是,这种方法要谨慎使用。首先,如果bean有一个属性,比如说amout,在当前的ServletRequest对象中却没有这个参数或者参数的值是"",于是以上动作没有起任何作用:JSP页面甚至不会用null值去设置bean的这个属性。于是,无论之前对bankClient的amount属性赋了任何值,这个bean都不会受任何影响。其次,没有定义属性编辑器(PropertyEditors)的非简单的属性可能不能由ServletRequest对象的一个字符串值隐式地初始化,需要显式地数据转换。第三,如果应用程序没有仔细地设计的话,恶意的用户能够在请求中添加另外的参数来设置bean的本来不想设置的属性。
如果你仍然喜欢在<jsp:setProperty>使用property="*"来达到获得比较简洁的代码,那么我们建议你在<jsp:setProperty>标签前加上注释来说明bean的初始化需要在ServletRequest对象中有哪些参数。在下面的例子中,通过注释我们知道初始化bankClient这个bean,firstName和lastName是必需的:
<%--
 - requires firstName and lastName from the ServletRequest
 --%>
<jsp:setProperty name="bankClient" property="*" />
 
12.2   JSP 隐含对象(JSP Implicit Objects)
直接使用JSP的隐含对象来获取对这些对象的引用要优于API调用。因此,不必使用
 
getServletConfig().getServletContext().getInitParameter("param")
 
来访问SerletContext实例提供的初始化参数,我们可以如下简单地使用隐含对象:
 
application.getInitParameter("param")
 
在仅仅需要输出初始化参数的值的情况下,最好使用JSTL标签来访问初始化参数:
 
<c:out value="${initParam['param']}" />
 
12.3   引号的使用(Quoting)
应该使用统一形式的引号。被引用的内容应该包含在两个双引号(“"”)之间而不是两个单引号(“'”)。
 
不统一的引号使用
优选的引号使用
<%@ page import= ' javabeans.* ' %>
<%@ page import="java.util.*" %>
<%@ page import="javabeans.*" %>
<%@ page import="java.util.*" %>
 
一个需要使用单引号的例外是,当脚本语言中需要使用双引号时:
 
    <jsp:include page='<%= getFoodMenuBar("Monday") %>' />
 
12.4   使用自定义标签(Using Custom Tags)
如果自定义标签没有体内容(body content),应该显式地声明content为empty(而不应默认为“JSP”),例如以下标签库描述符中的一段:
 
<tag>
    <name>hello</name>
    <tag-class>com.mycorp.util.taglib.HelloTagSupport</tag-class>
    <body-content>empty</body-content>
    ...
</tag>
 
以上配置告诉JSP容器体内容(body content)必须是空的,而不包含任何需要解析的JSP语法。这样能消除或避免为解析空的体内容(body content)而分配的不必要的资源。
空的标签应该是短XML元素,而不使用打开-关闭样式的XML元素对来提高可读性。于是,
<myTag:hello />
要优于
<myTag:hello></myTag:hello>
 
12.5   使用标签库附加信息和标签库校验器(Use of TagExtraInfo and TagLibraryValidator)
有些时候,仅用TLD不能够表达使用标签库的有效方法。因此这时就应该编写TagExtraInfo类和 TagLibraryValidator类,并在TLD中注册,于是在翻译的时候就能够捕捉到标签库的错误。
 
12.6   使用JavaScript(Use of JavaScript Technology)
为了使JavaScript运行正常,JavaScript不应该依赖于不同浏览器类型的某种特征。
将JavaScript代码放在独立的文件中同JSP文件分开是个好的方法,使用如下的一个语句就可以将JavaScript代码引入到JSP页面中:
    <script language=javascript src="/js/main.js">
 
12.7   嵌套式样式表(Cascading Style Sheets)
使用嵌套式样式表来集中对标题、表格等等共同特征的控制。这样提高了表现给用户的一致性,减少了维护的工作量和JSP页面的代码长度。因此,替代以下在HTML标签中嵌入样式信息的做法:
 
<H1><FONT color="blue">Chapter 1</FONT></H1>
...
<H1><FONT color="blue">Chapter 2</FONT></H1>
...
 
将样式信息定义在一个样式文件myJspStyle.css中,其内容包含:
 
H1 { color: blue }
 
在JSP页面使用该样式表:
 
<link rel="stylesheet" href="css/myJspStyle.css" type="text/css">
...
<H1>Chapter 1</H1>
...
<H1>Chapter 2</H1>
...
 
12.8   使用组合视图模式(Use of Composite View Patterns)
当JSP页面需要特定的合成的结构,这种结构也可能在其他JSP页面重复出现,有一种办法是将JSP页面分成若干部分,使用组合视图模式(参加Java BluePrints的模式部分)。例如,一个JSP页面在其呈现的结构上有时有以下的逻辑布局:
 
header
menu bar
main body
footnote
footer
 
在这种样式下,JSP页面可以分为不同模块,每一部分都作为JSP fragment。被组合的JSP fragment可以用翻译时(translation-time)或请求时(request-time)包含(include)的JSP标签来放在组合JSP页面的适当位置。通常,当使用静态包含指令包含一个不会单独请求的页面时,记得使用.jspf的后缀名,并且把这个文件放在这个WEB应用文档(war)的/WEB-INF/jspf/目录中。例如:
 
<%@ include file="/WEB-INF/jspf/header.jspf" %>
...
<%@ include file="/WEB-INF/jspf/menuBar.jspf" %>
...
<jsp:include page="<%= currentBody %>" />
...
<%@ include file="/WEB-INF/jspf/footnote.jspf" %>
...
<%@ include file="/WEB-INF/jspf/footer.jspf" %>
...
 
12.9   其他的建议
在本文中,我们提出了一套用来编写更可维护的和稳定的JSP代码和WEB组件的推荐编码规范。这里还有其他很好的编程惯例,如果你要想深入研究这些主题的话。例如:JSP 1.2规范建议:
l         定义新的隐式对象
l         访问提供者指定信息
l         自定义标签库
 
此外,Java BluePrints也在更广的范围提供了很好的编程惯例,例如Model-View-Controller模式的使用(在模式部分)。
    我们非常高兴你对本文提出的编程规范的关注,并且我们希望你能够共享你在JSP编码规范上的其他建议。请将你的反馈信息发送至 jsp-codeconv-comments@sun.com。
下面我们列出了一个完整的演示以上编码规范的WEB应用程序的源码。你可以在这里下载这个应用程序的WAR文件
 
13.     示例代码
这里列出了一个范例WEB应用程序来演示本文提出的编码规范。它包含包含在一个.war文件中的以下源码文件和目录结构:
 
/index.jsp
/WEB-INF/classes/codeconv/GetResultsTag.class
/WEB-INF/jspf/footer.jspf
/WEB-INF/lib/jstl.jar
/WEB-INF/lib/standard.jar
/WEB-INF/tld/lotterylib.tld
/WEB-INF/web.xml
 
index.jsp 页面使用了一个自定义标签库(由lotterylib.tld确定)查询当月每天(直到并包含当天)的假的抽奖结果。然后使用JSTL进行文本格式化,循环产生HTML的输出结果。
这个范例需要JSP 1.2和JSTL 1.0。
l         Source Listing for /index.jsp
 
14.     参考资料
 
2.       JSP best practices.
3.       Hans's Top Ten JSP Tips.
5.       Alur D., Crupi J., Malks D., Core J2EE Patterns: Best Practices and Design Strategies, Sun Microsystems Press, Prentice Hall Inc., 2001.
9.       JavaServer Faces Technology.
10.    Java BluePrints.
 
jsp编码规范 Java源文件       .java Java字节码文件     .class 动态页面        .jsp 静态页面        .html 脚本文件        .js 立即下载

相关推荐

从CORDIC到DDS:手把手拆解《Verilog传奇》第9章的实战项目(附可跑通的代码)

本文详细解析了如何从CORDIC算法到DDS系统的完整实现过程,基于《Verilog传奇》第9章的实战项目,提供了可运行的Verilog代码。内容涵盖CORDIC算法的硬件实现、DDS系统架构设计、完整系统集成与验证,以及实际部署中的性能调优技巧,适合数字IC和FPGA开发者深入学习。

weixin_42623010的博客 413

JSP的编写规范

1.为什么有jsp规范 Servlet技术产生后,在使用时最麻烦的是使用大量的out.print语句来输出页面。这样的形式在系统变更、维护、预览效果时都不能方便快捷的完成任务,于是推出JSP这种技术,用来将Servlet中负责显示的语句抽取出来。 Servlet向客户端浏览器返回一个HTML页面代码如下(大量的out.print语句,太过繁琐): public class HelloWorld extends HttpServlet { public void doGet(Ht

浅时光|初如梦 1871

用Matlab系统辨识工具箱搞定温控系统建模:从阶跃响应到传递函数(附完整代码)

本文详细介绍了如何使用Matlab系统辨识工具箱进行温控系统建模,从阶跃响应数据采集到传递函数参数辨识的全过程。通过实际案例和完整代码,帮助工程师快速掌握PID控制参数整定技巧,提升温控系统设计效率。特别适合单片机开发者和自动化控制工程师参考。

weixin_30736301的博客 310

Jsp编码规范

Jsp编码规范1.1 文件后缀(File Suffixes) 文件类别         文件后缀 -------------------------------------- Java源文件       .java Java字节码文件     .class 动态页面        .jsp 静态页面        .html 脚本文件        .js 1.2 常用文件名(Co

liubihai的专栏 792

无刷电机FOC控制入门:磁场、洛伦兹力与坐标转换详解

本文深入解析无刷电机FOC(磁场定向控制)的核心原理,从电磁学基础的磁场与洛伦兹力出发,详细阐述了如何通过Clarke变换、Park变换等坐标转换技术,将三相交流解耦为直流量进行控制,最终利用SVPWM技术实现平滑、高效的电机驱动。文章旨在帮助开发者理解FOC的物理本质与数学框架,为机器人、无人机等高性能应用奠定基础。

weixin_29306011的博客 267

【2023版】基于JT808/JT1078协议的车载视频监控平台开发实战-开源架构解析

本文详细解析了基于JT808/JT1078协议的车载视频监控平台开发实战,涵盖协议核心作用、开源架构设计、开发避坑指南及二次开发建议。重点介绍了JT1078协议在音视频传输中的优化方案,以及海量位置数据存储、高可用架构等关键技术点,为开发者提供全面的实战参考。

weixin_26965807的博客 236

JSP 编码规范

JSP 编码规范。jsp/jsp bean表示层应当尽可能的瘦和简单化。。牢记大多数的JSP都应当是只读的视图,而由页面bean来提供模型。。应当一起设计JSP和JSP bean。在尽可能合理的情况下,把业务逻辑从JSP中移走。具体于HTTP的逻辑(如,对Cookie的处理)属于bean或支持类中,而不是JSP中。。尽量把条件逻辑放在控制器中而不是放在视图中。。为JSP、包含的文件、JSP B

1172

MobaXterm简介和使用(服务器连接工具)

MobaXterm 是一个功能强大的远程计算工具,集成了许多常用的远程计算功能,包括 SSH、X11、RDP、VNC、FTP、SFTP 等。

清平乐的技术专栏 1950

一篇文章让你精通Java JSP规范

JSP基础 1.jsp和servlet的分工 jsp 作为请求发起页面,例如显示表单、超链接 作为请求结束页面,例如显示数据 servlet 作为请求中处理数据的环节 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j8vhBBAn-1594728087223)(en-resource://database/3015:1)] 2.jsp的组成 jsp = html + java脚本 + jsp标签(指令 jsp中无需创健即可使用的对象一共有9个,被称之

C++,网络,存储,音视频,虚拟化 304

使用conda环境python3.13和python3.12下安装vllm过程记录

使用conda环境python3.13和python3.12下安装vllm过程记录

没刮胡子的程序员专栏 885

YOLOv12改进策略【卷积层】| CVPR-2020 利用DynamicConv 动态卷积 结合A2C2f进行二次创新,提高精度

在大规模视觉预训练中,通常模型的性能受到数据、参数和FLOP三个关键因素的影响。一般来说,模型的参数数量越多,FLOP也越高,但在移动设备等对计算资源有限制的场景下,需要低FLOP的模型同时又希望模型能从大规模预训练中受益。传统的方法很难在增加参数的同时保持低FLOP,因此需要一种新的设计来解决这个问题,模块应运而生。

Limiiiing的博客 827

【JAVA编码规范】JAVA编码规范,超级详细的JAVA编码规范,太棒了,值得你通读一遍

【JAVA编码规范】JAVA编码规范,超级详细的JAVA编码规范,太棒了,值得你通读一遍 编码规范对于程序员而言尤为重要,有以下几个原因: 一个软件的生命周期中,80%的花费在于维护 几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护 规范可以改善软件的可读性,可以让程序员尽快而彻底地理解新的设计和代码 良好的编码规范可以有效避免一些低级错误

xzb5566的专栏 1万+

强化学习原理及应用作业之动态规划算法【SYSU_2023SpringRL】

本次实践作业将在以下环境进行: 该环境由一个 6×6 网格组成,其中黄色圆圈为智能体出发点,黑色格子为无法通过的墙壁,若智能体向着墙壁方向移动,则会停留在原地,地图边界的移动同理。带有黄色边框的格子为终止状态,即若智能体行动至此状态则整个 episode 结束。红色和绿色表示当前该状态的奖励值,奖励越高则绿色越深,奖励越低则红色越深。状态空间:36(0-35 这 36 个整数,左下角为 0,向右 +1,向上 +6)动作空间:4(0-3 这 4 个整数分别代表左、右、上、下)奖励函数:普通格子 -0.1,到

zik的博客 1398

【1+X Java Web应用考证】关于2021 “1+X ”Java Web应用 等级考证方向

关于 “1+X” ☞ 职业技能等级证书信息管理服务平台 “1+X” 的概念来自于2019年教育部在《国家职业教育改革实施方案》中提出在职业院校、应用型本科高校启动“学历证书+职业技能等级证书”(即 1+X证书)制度试点,鼓励学生在获得学历证书的同时,积极取得多类职业技能等级证书。 自从2019年开始试点到现在已经第三年了,前两年的1+X web 前端是以前端基础 (HTML,CSS,HTML5,CSS3,JS,JQ,Bootstrap,高级web加入Vue前端技术栈框架基础),MySql 基础,后端以php

go 1万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Struts 1.x的线程安全

回到首页☞ 第一轮做基础知识整理并没有那么深入,跳过了struts 1.x 的实例,一个完整的项目起码要有: 权限管理模块 安全加固模块-防入侵 UI web交互模块 业务层,业务逻辑封装模块 dao层数据处理模块–基础的是纯纯的JDBC 数据跟踪,异常干涉模块 入湖模块,OGG等是必不可少的,因为数据是企业命脉。 先简单的回顾,然后按需,第二轮,第三轮完善。 线程安全是每个多线程程序都要考虑...

JDIT的博客 219

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

JavaWeb开发系列(六)JSP基础

JSP(Java Server Pages)是一种动态网页技术,允许在HTML中嵌入Java代码。文章详细介绍了JSP的基本语法,包括脚本片段、表达式、声明等元素,并提供了完整的JSP页面示例。同时讲解了JSP指令类型(page、include、taglib)及其属性,以及九大隐含对象(如request、response、session等)的功能和使用场景。此外,还对比了四种作用域(page、request、session、application)的生命周期和适用情况,并列举了常用的JSP动作标签(如inc

echo的博客 886

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

软件框架以及编码规范说明文档

1 文档简介 此文档主要是描述软件架构和编码的技术规范。详细地说明所确定的整个框架所涉及到的技术的外部行为,以及表现形式。另外,涉及到具体编写代码时,类、方法的命名规范。 2 软件框架 2.1 框架介绍 本框架主要是基于Hibernate 3.0 + Struts 1.2.x + Servlet 2.4 + Jsp 2.0 + JSTL 1.2...

weixin_33974433的博客 182

JSP

   概要:     JSP规范的不断进展,可用的jsp开发工具数量不断增多,以及jsp技术可涉及领域的不断的扩展,促进了基于jsp技术的高维护性能和标准化的网络应用的开发。这篇文章讨论了在jsp进展中的一些主要内容以及如何更容易的开发健壮的JSP网络应用。这篇文章可以帮助读者提高应用JSP强大功能的能力,并能够让你为将来JSP的升级做好准备。  自从我(原文作者)在2001年底发表了“JSP最

archangelminrui417的专栏 526

终极指南:如何在Tomcat中高效应用JSP标准标签库(JSTL)

想要在Tomcat中快速掌握JSP标准标签库(JSTL)的应用技巧吗?本指南将为你提供完整的JSTL应用解决方案,帮助你轻松提升Java Web开发效率。JSTL作为Tomcat服务器中重要的标签库组件,能够显著简化JSP页面的开发复杂度。 ## 🔥 什么是JSTL及其在Tomcat中的重要性 JSTL(JavaServer Pages Standard Tag Library)是一套标准化

gitblog_00940的博客 1152

耗时1年的前端技术框架切换之旅

摘要:一个电话,我便开启了为期1年的前端技术框架切换之旅。

华为云官方博客 5500

JSP最新特性及思想的最佳实践

   概要:     JSP规范的不断进展,可用的jsp开发工具数量不断增多,以及jsp技术可涉及领域的不断的扩展,促进了基于jsp技术的高维护性能和标准化的网络应用的开发。这篇文章讨论了在jsp进展中的一些主要内容以及如何更容易的开发健壮的JSP网络应用。这篇文章可以帮助读者提高应用JSP强大功能的能力,并能够让你为将来JSP的升级做好准备。  自从我(原文作者)在2001年底发表了“JSP最

868

当年的java考试:Java景区预约登记管理系统(maven整合servlet)

maven整合servlet的过程以及使用mybatis框架进行CRUD操作 需求效果: 1、搭建maven整合servlet(10分) 2、mybatis各种配置(创建数据库)(10分) 3、完成各层编码与联系(30分) 4、在DAO层进行编码测试(0分) 5、在servlet层创建查询GetInfo、添加AddInfo、修改SelectById,UpdateById,删除DeleteById(30分) 6、完成视图层编码,GetInfo.jsp,AddInfo.jsp(10分) 7、(编码规范

红目香薰 2067

eclipse的jsp第一行代码报错_你写的代码很丑?整理了下这些 Python 编码规范

点击上方Python知识圈,选择设为星标回复1024获取Python资料阅读文本大概需要 5 分钟。python 文件的组成为了便于描述,先上一个 demo#!/usr/bin/env python# -*- coding: utf-8 -*-"""通常这里是关于本文档的说明(docstring),须以半角的句号、 问号或惊叹号结尾!本行之前应当空一行,继续完成关于本文档的说明如果文档说...

weixin_32952295的博客 151

JSP乱码解决之 pageEncoding和contentType属性,UTF-8 GBK gb2312 详解

JSP乱码解决 之 pageEncoding和contentType属性,UTF-8 GBK gb2312 详解 UTF-8编码是什么? UTF-8 编码是一种被广泛应用的编码,这种编码致力于把全球的语言纳入一个统一的编码,目前已经将几种亚洲语言纳入。UTF 代表 UCS Transformation Format. UTF-8 采用变长度字节来表示字符,理论上最多可以到...

wjboy49的专栏 1053
上一篇: 在 Eclipse 中将 Java Project 作为 Resin 项目攻略
下一篇: Java FAQ(新手必看)
tiny_yan
博客等级 码龄26年 3粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值