zoukankan      html  css  js  c++  java
  • Java:JSP

    ylbtech-Java:JSP
    1.返回顶部
    1、
    JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML(标准通用标记语言的子集)文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。
    它实现了Html语法中的java扩展(以 <%, %>形式)。JSP与Servlet一样,是在服务器端执行的。通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览。
    JSP技术使用Java编程语言编写类XML的tags和scriptlets,来封装产生动态网页的处理逻辑。网页还能通过tags和scriptlets访问存在于服务端的资源的应用逻辑。JSP将网页逻辑与网页设计的显示分离,支持可重用的基于组件的设计,使基于Web的应用程序的开发变得迅速和容易。 JSP(JavaServer Pages)是一种动态页面技术,它的主要目的是将表示逻辑从Servlet中分离出来。
    Java Servlet是JSP的技术基础,而且大型的Web应用程序的开发需要Java Servlet和JSP配合才能完成。JSP具备了Java技术的简单易用,完全的面向对象,具有平台无关性且安全可靠,主要面向因特网的所有特点
    2、
    2.返回顶部
    1、
    发展历程
    1.2版本
    JSP1.2不支持EL,但可以使用外部的JSTL标签以便使用EL。 
    2.0版本
    JSP 2.0的一个主要特点是它支持表达语言(expression language)。JSTL表达式语言可以使用标记格式方便地访问JSP的隐含对象和JavaBeans组件,JSTL的核心标记提供了流程和循环控制功能自制标记也有自定义函数的功能,因此基本上所有scriptlet能实现的功能都可以由JSTL替代。在JSP 2.0中,建议尽量使用EL而使JSP的格式更一致。
    SimpleTag
    JSP 2.0中加入了新的创建自制标记的API,javax.servlet.jsp.tagext.SimpleTag定义了用来实现简单标记的接口。和 JSP 1.2中的已有接口不同的是,SimpleTag接口不使用doStartTag和doEndTag方法,而提供了一个简单的doTag方法。这个方法在调用该标记时只被使用一次。而需要在一个自制标记中实现的所有逻辑过程、循环和对标记体的评估等都在这个方法中实现。从这个方面来讲, SimpleTag和IterationTag可以达到同等的作用。但SimpleTag的方法和处理周期要简单得多。在SimpleTag中还有用来设置JSP内容的setJspBody和getJspBody方法。Web容器会使用setJspBody方法定义一个代表JSP内容的 JspFragment对象。实现SimpleTag标记的程序可以在doTag方法中根据需要多次调用getJspBody.invoke方法以处理JSP内容。
    重要功能
    JSP2.0中的一个主要功能是JSP fragment,它的基本特点是可以使处理JSP的容器推迟评估JSP标记属性。我们知道一般JSP是首先评估JSP标记的属性,然后在处理JSP标记时使用这些属性,而JSP fragment提供了动态的属性。也就是说,这些属性在JSP处理其标记体时是可以被改变的。JSP需要将这样的属性定义为 javax.servlet.jsp.tagext.JspFragment类型。当JSP标记设置成这种形式时,这种标记属性实际上的处理方法类似于标记体。在实现标记的程序中,标记属性可以被反复评估多次。这种用法称为JSP fragment。JSP fragment还可以定义在一个SimpleTag处理程序中使用的自制标记动作。像前面例子说明的,getJspBody返回一个 JspFragment对象并可以在doTag方法中多次使用。需要注意的是,使用JSP fragment的JSP只能有一般的文本和JSP action,不能有scriptlet和scriptlet表达式。
     
    2、
    3. 语言标准返回顶部
    1、
    语言标准
    句法
    一个JSP页面可以被分为以下几部份:
    • 静态数据,如HTML
    • JSP指令,如include指令
    • JSP脚本元素和变量
    • JSP动作
    • 用户自定义标签
    静态数据
    静态数据在输入文件中的内容和输出给HTTP响应的内容完全一致。此时,该JSP输入文件会是一个没有内嵌JAVA或动作的HTML页面。而且,客户端每次请求都会得到相同的响应内容。
    JSP指令
    JSP指令控制JSP编译器如何去生成servlet,以下是可用的指令:
    • 包含指令include –包含指令通知JSP编译器把另外一个文件完全包含入当前文件中。效果就好像被包含文件的内容直接被粘贴到当前文件中一样。这个功能和C预处理器所提供的很类似。被包含文件的扩展名一般都是"jspf"(即JSPFragment,JSP碎片):
    <%@ include file="somefile.jsp" %>
    • 页面指令page –页面指令有以下几个选项:
    import
    使一个JAVA导入声明被插入到最终页面文件。
    contentType
    规定了生成内容的类型。当生成非HTML内容或者当前字符集character set并非默认字符集时使用。
    errorPage
    处理HTTP请求时,如果出现异常则显示该错误提示信息页面。
    isErrorPage
    如果设置为TRUE,则表示当前文件是一个错误提示页面。
    isThreadSafe
    表示最终生成的servlet是否安全线程(threadsafe)。
    <%@ page import="java.util.*" %> //example import导入样例
    <%@ page contentType="text/html" %> //example contentType页面类型样例
    <%@ page isErrorPage=false %> //example for non error page无错页面样例
    <%@ page isThreadSafe=true %> //example for a thread safe JSP安全线程JSP样例
    注意:在同一个JSP文件中只有"import"导入页面指令可以被多次使用。
    • 标签库指令taglib –标签库指令描述了要使用的JSP标签库。该指令需要指定一个前缀prefix(和C++的命名空间很类似)和标签库的描述URI:
    <%@ taglib prefix="myprefix" uri="taglib/mytag.tld" %>
    JSP脚本
    标准脚本变量
    以下是永远可用的脚本变量:
    • out – JSPWriter用来写入响应流的数据
    • page – servlet自身
    • pageContext –一个PageContext实例包括和整个页面相联系的数据,一个给定的HTML页面可以在多个JSP之间传递。
    • request –HTTP request对象
    • response –HTTP response对象
    • session –用于保持客户端与服务器连接的对象
    脚本元素
    有三个基本的脚本元素,作用是使JAVA代码可以直接插入servlet.
    • 一种是声明标签,在JAVA SERVLET的类体中放入一个变量的定义。静态的数据成员也可以如此定义。
      • <%! int serverInstanceVariable = 1; %>
    • 一种是脚本标签,在JAVA SERVLET的类的_jspService()方法中放入所包含的语句。
      • <% int localStackBasedVariable = 1; out.println(localStackBasedVariable); %>
    • 一种是表达式标签,在JAVA SERVLET的类中放入待赋值的表达式,表达式注意不能以分号结尾。
      • <%= "expanded inline data " + 1 %>
    JSP动作
    JSP动作是一系列可以调用内建于网络服务器中的功能的XML标签。JSP提供了以下动作:
    jsp:include
    和子过程类似,JAVA SERVLET暂时接管对其它指定的JSP页的请求和响应。当处理完该JSP页后就马上把控制权交还当前JSP页。这样JSP代码就可以在多个JSP页中共享而不用复制。
    jsp:param
    可以在jsp:include, jsp:forward或jsp:params块之间使用。指定一个将加入请求的当前参数组中的参数。
    jsp:forward
    用于处理对另一个JSP或SERVLET的请求和响应。控制权永远不会交还给当前JSP页。
    jsp:plugin
    Netscape Navigator的老版本和Internet Explorer使用不同的标签以嵌入一个applet。这个动作产生为嵌入一个APPLET所需要的指定浏览器标签。
    jsp:fallback
    如果浏览器不支持APPLETS则会显示的内容。
    jsp:getProperty
    从指定的JavaBean中获取一个属性值。
    jsp:setProperty
    在指定的JavaBean中设置一个属性值。
    jsp:useBean
    创建或者复用一个JavaBean变量到JSP页。
    技术方法
    为了快速方便地进行动态网站的开发,JSP在以下几个方面做了改进,使其成为快速建立跨平台的动态网站的首选方案。
    1.将内容的生成和显示进行分离
    用JSP技术,Web页面开发人员可以使用HTML或者XML标识来设计和格式化最终页面,并使用JSP标识或者小脚本来生成页面上的动态内容(内容是根据请求变化的,例如请求账户信息或者特定的一瓶酒的价格等)。生成内容的逻辑被封装在标识和JavaBeans组件中,并且捆绑在脚本中,所有的脚本在服务器端运行。由于核心逻辑被封装在标识和JavaBeans中,所以Web管理人员和页面设计者,能够编辑和使用JSP页面,而不影响内容的生成。
    在服务器端,JSP引擎解释JSP标识和脚本,生成所请求的内容(例如,通过访问JavaBeans组件,使用JDBC技术访问数据库或者包含文件),并且将结果以HTML(或者XML)页面的形式发送回浏览器。这既有助于作者保护自己的代码,又能保证任何基于HTML的Web浏览器的完全可用性。
    可重用组件
    绝大多数JSP页面依赖于可重用的、跨平台的组件(JavaBeans或者Enterprise JavaBeans组件)来执行应用程序所要求的复杂的处理。开发人员能够共享和交换执行普通操作的组件,或者使得这些组件为更多的使用者和客户团体所使用。基于组件的方法加速了总体开发过程,并且使得各种组织在他们现有的技能和优化结果的开发努力中得到平衡。
    采用标识
    Web页面开发人员不会都是熟悉脚本语言的编程人员。JSP技术封装了许多功能,这些功能是在易用的、与JSP相关的XML标识中进行动态内容生成所需要的。标准的JSP标识能够访问和实例化JavaBeans组件,设置或者检索组件属性,下载Applet,以及执行用其他方法更难于编码和耗时的功能。
    适应平台
    几乎所有平台都支持Java,JSP+JavaBeans几乎可以在所有平台下通行无阻。从一个平台移植到另外一个平台,JSP和JavaBeans甚至不用重新编译,因为Java字节码都是标准的与平台无关的。
    数据库连接
    Java中连接数据库的技术是JDBC,Java程序通过JDBC驱动程序与数据库相连,执行查询、提取数据等操作。Sun公司还开发了JDBC-ODBC bridge,利用此技术Java程序可以访问带有ODBC驱动程序的数据库,大多数数据库系统都带有ODBC驱动程序,所以Java程序能访问诸如Oracle、Sybase、MS SQL Server和MS Access等数据库。
    此外,通过开发标识库,JSP技术可以进一步扩展。第三方开发人员和其他人员可以为常用功能创建自己的标识库。这使得Web页面开发人员能够使用熟悉的工具和如同标识一样的执行特定功能的构件来进行工作。
    JSP技术很容易整合到多种应用体系结构中,以利用现存的工具和技巧,并且能扩展到支持企业级的分布式应用中。作为采用Java技术家族的一部分,以及Java 2(企业版体系结构)的一个组成部分,JSP技术能够支持高度复杂的基于Web的应用。 由于JSP页面的内置脚本语言是基于Java的,而且所有的JSP页面都被编译成为Java Servlets,所以JSP页面具有Java技术的所有好处,包括健壮的存储管理和安全性。作为Java平台的一部分,JSP拥有Java编程语言“一次编写,各处运行”的特点。
    语言特点
    优点
    (1)一次编写,到处运行。除了系统之外,代码不用做任何更改。
    (2)系统的多平台支持。基本上可以在所有平台上的任意环境中开发,在任意环境中进行系统部署,在任意环境中扩展。相比ASP的局限性JSP的优势是显而易见的。
    (3)强大的可伸缩性。从只有一个小的Jar文件就可以运行Servlet/JSP,到由多台服务器进行集群和负载均衡,到多台Application进行事务处理,消息处理,一台服务器到无数台服务器,Java显示了一个巨大的生命力。
    (4)多样化和功能强大的开发工具支持。这一点与ASP很像,Java已经有了许多非常优秀的开发工具,而且许多可以免费得到,并且其中许多已经可以顺利的运行于多种平台之下。
    JSPJSP
    (5)支持服务器端组件。web应用需要强大的服务器端组件来支持,开发人员需要利用其他工具设计实现复杂功能的组件供web页面调用,以增强系统性能。JSP可以使用成熟的JAVA BEANS 组件来实现复杂商务功能
    缺点
    (1) 与ASP也一样,Java的一些优势正是它致命的问题所在。正是由于为了跨平台的功能,为了极度的伸缩能力,所以极大的增加了产品的复杂性
    (2) Java的运行速度是用class常驻内存来完成的,所以它在一些情况下所使用的内存比起用户数量来说确实是“最低性能价格比”了。
    2、
    4. 语言组成、语言对比返回顶部
    1、
    语言组成
    内置对象
    request
    request 对象是 javax.servlet.httpServletRequest类型的对象。 该对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。(包括头信息、系统信息、请求方式以及请求参数等)。request对象的作用域为一次请求。
    response
    response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。response对象也具有作用域,它只在JSP页面内有效。
    session
    1.什么是session:从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。当一个客户访问一个服务器时,可能会在这个服务器的几个页面之间反复连接,反复刷新一个页面,服务器应当通过某种办法知道这是同一个客户,这就需要session对象。
    2.session对象的ID:当一个客户首次访问服务器上的一个JSP页面时,JSP引擎产生一个session对象,同时分配一个String类型的ID号,JSP引擎同时将这个ID号发送到客户端,存放在Cookie中,这样session对象和客户之间就建立了一一对应的关系。当客户再访问连接该服务器的其他页面时,不再分配给客户新的session对象,直到客户关闭浏览器后,服务器端该客户的session对象才取消,并且和客户的会话对应关系消失。当客户重新打开浏览器再连接到该服务器时,服务器为该客户再创建一个新的session对象。
    3.session对象存在一定时间过期问题,所以存在session中的名值对会在一定时间后失去,可以通过更改session有效时间来避免这种情况。同时编程时尽量避免将大量有效信息存储在session中,request是一个不错的替代对象。
    application
    1.什么是application:
    服务器启动后就产生了这个application对象,当客户在所访问的网站的各个页面之间浏览时,这个application对象都是同一个,直到服务器关闭。但是与session不同的是,所有客户的application对象都是同一个,即所有客户共享这个内置的application对象。
    2.application对象常用方法:
    (1)public void setAttribute(String key,Object obj): 将参数Object指定的对象obj添加到application对象中,并为添加的对象指定一个索引关键字。
    (2)public Object getAttribute(String key): 获取application对象中含有关键字的对象。
    out
    out 对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区。在使用 out 对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区中的残余数据,为其他的输出让出缓冲空间。待数据输出完毕后,要及时关闭输出流。
    page
    page 对象代表JSP本身,只有在JSP页面内才是合法的。 page隐含对象本质上包含当前 Servlet接口引用的变量,类似于Java编程中的 this 指针。
    config
    config 对象的主要作用是取得服务器的配置信息。通过 pageContext对象的 getServletConfig() 方法可以获取一个config对象。当一个Servlet 初始化时,容器把某些信息通过 config对象传递给这个 Servlet。 开发者可以在web.xml 文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。
    exception
    java.lang.Throwable 的实例,该实例代表其他页面中的异常和错误。只有当页面是错误处理页面,即编译指令page 的isErrorPage 属性为true 时,该对象才可以使用。常用的方法有getMessage()和printStackTrace()等。
    pageContext
    pageContext 对象的作用是取得任何范围的参数,通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用 pageContext对象。
     
     
    语言对比
    与servlets的区别
    从架构上说,JSP可以被看作是从Servlets高级提炼而作为JAVA Servlet2.1 API的扩展而应用。Servlets和JSP最早都是由Sun Microsystems(升阳公司)开发的。从JSP1.2版本以来,JSP处于Java Community Process(有人译为:JAVA社区组织)开发模式下。JSR-53规定了JSP 1.2和Servlet 2.4的规范,JSR-152规定了JSP 2.0的规范。2006年5月,JSP 2.1的规范作为Java EE5的一部份,在JSR-245中发布。
    与ASP的比较
    JSP(Java Server Page)与ASP(Active Server Page)两者都是常用的动态网页技术,也都是可以嵌入HTML中的程序,但两者是有着本质的不同,主要从以下几个方面对其进行比较:
    1.Web服务器的支持:大多数通用的 Web服务器如:Apache、Netscape和Microsoft IIS都支持JSP页面,只有微软本身的Microsoft IIS和Personal Web Server可以支持ASP。
    2.平台的支持:JSP具有平台独立性,只要是一般的Java程序可以运行的平台,都支持JSP程序。Windows平台可以很好的支持ASP,但ASP对于基于Win32逐渐模型的依赖,使得它难于移植到其它平台上。
    3.组件模型:JSP是建立在可重用的、跨平台的组件(如:JavaBeans、Enterprises JavaBeans和用户定制的标签库等组件)之上的,而ASP使用的是基于Win32的COM组件模型。
    4.脚本语言:JSP可以使用Java编程语言或JavaScript作为脚本语言,而ASP使用VBScript或Jscript作为脚本语言。
    5.安全性:JSP使用Java安全模型,而ASP使用Windows NT的安全结构。
    6.与Access数据库的连接:JSP使用JDBC建立与Access数据库的连接,而ASP对Access数据库使用Data Active Objects。
    7.用户定制的标签:JSP可以使用用户定制标签库进行扩充,而ASP中没有用户定制标签库,ASP是不能扩充的。
     
    2、
    5. JSP标准标签库返回顶部
    1、
    根据JSTL标签所提供的功能,可以将其分为5个类别。
    • 核心标签
    • 格式化标签
    • SQL 标签
    • XML 标签
    • JSTL 函数
    JSTL 库安装
    Apache Tomcat安装JSTL 库步骤如下:
    • 从Apache的标准标签库中下载的二进包(jakarta-taglibs-standard-current.zip)。下载地址:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/
    • 下载jakarta-taglibs-standard-1.1.1.zip 包并解压,将jakarta-taglibs-standard-1.1.1/lib/下的两个jar文件:standard.jar和jstl.jar文件拷贝到/WEB-INF/lib/下。
    使用任何库,你必须在每个JSP文件中的头部包含<taglib>标签。
     
    核心标签
    核心标签是最常用的JSTL标签。引用核心标签库的语法如下:
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    标签
    描述
    <c:out >
    用于在JSP中显示数据,就像<%= ... >
    <c:set >
    用于保存数据
    <c:remove >
    用于删除数据
    <c:catch>
    用来处理产生错误的异常状况并且将错误信息储存起来
    <c:if>
    与我们在一般程序中用的if一样
    <c:choose>
    本身只当做<c:when>和<c:otherwise>的父标签
    <c:when>
    <c:choose>的子标签,用来判断条件是否成立
    <c:otherwise >
    <c:choose>的子标签,接在<c:when>标签后当<c:when>标签判断为false时被执行
    <c:import>
    检索一个绝对或相对 URL,然后将其内容暴露给页面
    <c:forEach >
    基础迭代标签接受多种集合类型
    <c:forTokens>
    根据指定的分隔符来分隔内容并迭代输出
    <c:param>
    用来给包含或重定向页面传递参数
    <c:redirect >
    重定向至一个新的URL
    <c:url>
    使用可选的查询参数来创造一个URL
     
    格式化标签
    JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    标签
    描述
    <fmt:formatNumber>
    使用指定的格式或精度格式化数字
    <fmt:parseNumber>
    解析一个代表着数字,货币或百分比的字符串
    <fmt:formatDate>
    使用指定的风格或模式格式化日期和时间
    <fmt:parseDate>
    解析一个代表着日期或时间的字符串
    <fmt:bundle>
    绑定资源
    <fmt:setLocale>
    指定地区
    <fmt:setBundle>
    绑定资源
    <fmt:timeZone>
    指定时区
    <fmt:setTimeZone>
    指定时区
    <fmt:message>
    显示资源配置文件信息
    <fmt:requestEncoding>
    设置request的字符编码
     
    SQL标签
    JSTL SQL标签库提供了与关系型数据库(Oracle,MySQL,SQL Server等等)进行交互的标签。引用SQL标签库的语法如下:
    <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
    标签
    描述
    <sql:setDataSource>
    指定数据源
    <sql:query>
    运行SQL查询语句
    <sql:update>
    运行SQL更新语句
    <sql:param>
    将SQL语句中的参数设为指定值
    <sql:dateParam>
    将SQL语句中的日期参数设为指定的java.util.Date 对象值
    <sql:transaction >
    在共享数据库连接中提供嵌套的数据库行为元素将所有语句以一个事务的形式来运行
     
    XML 标签
    JSTL XML标签库提供了创建和操作XML文档的标签。引用XML标签库的语法如下:
    <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
    在使用xml标签前,你必须将XML 和 XPath 的相关包拷贝至你的<Tomcat 安装目录>lib下:
      • XercesImpl.jar:
    xalan.jar:
    • 标签
    描述
    <x:out>
    与<%= ... >,类似,不过只用于XPath表达式
    <x:parse>
    解析 XML 数据
    <x:set >
    设置XPath表达式
    <x:if >
    判断XPath表达式,若为真,则执行本体中的内容,否则跳过本体
    <x:forEach>
    迭代XML文档中的节点
    <x:choose>
    <x:when>和<x:otherwise>的父标签
    <x:when >
    <x:choose>的子标签,用来进行条件判断
    <x:otherwise >
    <x:choose>的子标签,当<x:when>判断为false时被执行
    <x:transform >
    将XSL转换应用在XML文档中
    <x:param >
    与<x:transform>共同使用,用于设置XSL样式表
     
    JSTL函数
    JSTL包含一系列标准函数,大部分是通用的字符串处理函数。引用JSTL函数库的语法如下:
    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
    函数
    描述
    fn:contains()
    测试输入的字符串是否包含指定的子串
    fn:containsIgnoreCase()
    测试输入的字符串是否包含指定的子串,大小写不敏感
    fn:endsWith()
    测试输入的字符串是否以指定的后缀结尾
    fn:escapeXml()
    跳过可以作为XML标记的字符
    fn:indexOf()
    返回指定字符串在输入字符串中出现的位置
    fn:join()
    将数组中的元素合成一个字符串然后输出
    fn:length()
    返回字符串长度
    fn:replace()
    将输入字符串中指定的位置替换为指定的字符串然后返回
    fn:split()
    将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回
    fn:startsWith()
    测试输入字符串是否以指定的前缀开始
    fn:substring()
    返回字符串的子集
    fn:substringAfter()
    返回字符串在指定子串之后的子集
    fn:substringBefore()
    返回字符串在指定子串之前的子集
    fn:toLowerCase()
    将字符串中的字符转为小写
    fn:toUpperCase()
    将字符串中的字符转为大写
    fn:trim()
    移除首位的空白符
    2、
     
    6.返回顶部
    warn 作者:ylbtech
    出处:http://ylbtech.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    IE的hasLayout
    《那些年啊,那些事——一个程序员的奋斗史》——101
    《那些年啊,那些事——一个程序员的奋斗史》——101
    《那些年啊,那些事——一个程序员的奋斗史》——101
    《那些年啊,那些事——一个程序员的奋斗史》——103
    《那些年啊,那些事——一个程序员的奋斗史》——102
    《那些年啊,那些事——一个程序员的奋斗史》——102
    《那些年啊,那些事——一个程序员的奋斗史》——103
    《那些年啊,那些事——一个程序员的奋斗史》——103
    《那些年啊,那些事——一个程序员的奋斗史》——102
  • 原文地址:https://www.cnblogs.com/storebook/p/9560810.html
Copyright © 2011-2022 走看看