Java语言程序设计JSP程序设计谷风详析

上传人:壹****1 文档编号:568831290 上传时间:2024-07-27 格式:PPT 页数:104 大小:1.57MB
返回 下载 相关 举报
Java语言程序设计JSP程序设计谷风详析_第1页
第1页 / 共104页
Java语言程序设计JSP程序设计谷风详析_第2页
第2页 / 共104页
Java语言程序设计JSP程序设计谷风详析_第3页
第3页 / 共104页
Java语言程序设计JSP程序设计谷风详析_第4页
第4页 / 共104页
Java语言程序设计JSP程序设计谷风详析_第5页
第5页 / 共104页
点击查看更多>>
资源描述

《Java语言程序设计JSP程序设计谷风详析》由会员分享,可在线阅读,更多相关《Java语言程序设计JSP程序设计谷风详析(104页珍藏版)》请在金锄头文库上搜索。

1、第十二章第十二章 JSP程序设计程序设计JAVA语言程序设计1特制分析目录目录l12.1 JSP简介简介l12.2 JSP与与JavaBeanl12.3 JSP标签库标签库l12.4 JSP与与Servletl12.5 本章小结本章小结2特制分析12.1 JSP简介简介lservlet和和JSP(JavaServer Page)已成为开发电子商务等动态网站的首选技术,它们都是运行在服务器上的Java程序servletlHTML的编写和维护都比较困难,使用print语句生成HTML并不容易,非Java开发人员很难处理这些HTMLJSPl静态内容的输出都采用标准的HTML,只用java语言编写页面

2、中生成动态内容的代码l提供了对Java编程语言以及针对动态部分的servlet技术的完全访问3特制分析12.1.1 什么是什么是JSP程序程序lJSP简单的说,就是嵌入了Java代码的HTML,由静态HTML、专用的JSP标签和Java代码组成服务器端的技术。在后台被自动转换成servlet仅在修改后的第一次被访问时,才会被转换成servlet并进行编译,创建JSP唯一的一个一实例,并调用_jspInit完成初始化,之后每个用户请求都会创建一个调用JSP实例的_jspService方法的线程。因而多个并发请求会导致多个线程同时调用_jspServiceTomcat中,默认目录下的JSP文件被转

3、换生成的servlet文件及编译后生成的class文件被放在install_dir/work/ Catalina/ localhost/ _/org/apache/jsp目录下JSP简介4特制分析12.1.1 什么是什么是JSP程序程序 JSP页面被请求后的操作页面被请求后的操作JSP简介 将JSP页面转换为servlet编译servlet将servlet载入到服务器内存中调用jspInit调用_jspService页面初次创建请求1有有有有有请求2无无无无有服务器重启后请求3无无有有有请求4无无无无有页面修改后请求5有有有有有请求6无无无无有5特制分析lJSP文件在服务器的部署文件在服务器的

4、部署可以和常规的HTML页面放在相同的目录中,并使用和常规HTML相同的URL访问它们除了不允许将WEB-INF和META-INF作目录名之外,可以使用任何喜欢的目录名Tomcat中JSP的默认目录是install_dir/webapps/ROOT,我们只要把编写好的JSP文件直接放在此目录下即可l例如install_dir/webapps/ROOT/SomeDirectory/SomeFile.jspl则对应的URL为http:/host:port/SomeDirectory/SomeFile.jsp12.1.1 什么是什么是JSP程序程序 JSP文件在服务器的部署文件在服务器的部署JSP简

5、介6特制分析12.1.2 JSP语法概述语法概述l除了标准的除了标准的HTML以外,以外,JSP主要包括三类组件主要包括三类组件脚本元素(scripting elements)l使你可以向JSP文件产生的servlet文件中插入代码指令标签(directives)l将影响由JSP页产生的servlet的总体结构动作标签(actions)l影响JSP运行时的功能JSP简介7特制分析l脚本元素脚本元素向向JSP文件产生的文件产生的servlet文件中插入文件中插入代码,主要有三种形式代码,主要有三种形式表达式 l%和=之间不能有空格。expression必须能求值,服务器计算出值后以字符串形式发送

6、到客户端显示程序片l一个JSP页面可以有许多,它们将被插入到生成的servlet文件的_jspService方法中l每次客户端请求都会新开一个线程,调用servlet的service方法,service方法再调用_jspService方法JSP简介12.1.2 JSP语法概述语法概述 脚本元素脚本元素8特制分析声明语句l声明的内容包括变量和方法,将被插入到生成servlet的类体中,在_jspService方法之外,成为类变量和类方法,直到服务器关闭才被释放l当多个客户请求一个JSP页面时,多个线程将共享这些变量和方法,因而任何一个用户对这些变量操作的结果,都会影响到其他用户12.1.2 JS

7、P语法概述语法概述 脚本元素脚本元素JSP简介9特制分析l指令标签指令标签将影响由JSP页产生的servlet的总体结构其格式为ldirective代表指令名称lattribute代表该指令中可选的属性名称lvalue代表属性值并且总是用单引号或双引号括起来,要想在属性值value中输出引号,可在该引号前用一个反斜杠“”在JSP中,有三种类型的指令lpagelincludeltaglibJSP简介12.1.2 JSP语法概述语法概述 指令标签指令标签10特制分析lpage指令指令可放在文档内的任何位置,该指令对整个页面有效可以定义一个或多个大小写敏感的属性,包括import、contentTy

8、pe、isThreadSafe、Session、buffer等import属性l为JSP页面引入Java核心包中的类,这样就可以在脚本部分使用这些类,如: l可以为import属性指定多个值,这些值用逗号分割,这样就可以引入若干个包或类,如: lJSP页面默认import属性已经有如下的值:java.lang.*, javax.servlet.*,javax.servlet.jsp.*,javax.servlet.http.*“l除import属性外,Page指令的其它属性只能指定一个值JSP简介12.1.2 JSP语法概述语法概述 指令标签指令标签/page指令指令11特制分析content

9、Type属性l定义JSP页面相应的MIME(Multipurpose Internet Mail Extension,多用途Internet 邮件扩展)类型和JSP页面字符编码l其属性使用以下两种格式之一 或者l例如l其属性默认值为JSP简介12.1.2 JSP语法概述语法概述 指令标签指令标签/page指令指令12特制分析isThreadSafe属性l用来设置JSP页面是否可多线程访问l设为true时,JSP页面能同时响应多个客户的请求l设为false时,同一时刻只能处理一个客户的请求,其它客户须等待l其默认值为truesession属性l表示当前的JSP页面是否参与HTTP会话l设为tru

10、e时,可以使用内置的javax.Servlet.HttpSession类型的一个名为session的对象l设为false时,则该对象不被创建l默认值为trueJSP简介12.1.2 JSP语法概述语法概述 指令标签指令标签/page指令指令13特制分析buffer属性l指定jsp内置输出流out变量使用的缓冲区的尺寸,如果设置为none,则不使用缓冲区l默认值是8kblout变量是JspWriter类型的,JspWriter是java.io.Writer类的子类。累计输出内容超过了这里设定的大小、完成了此页、或者输出被明确清除(如使用response. flushBuffer),文档才被发送给

11、客户显示l例如 autoflush属性l控制out的缓冲区在装满时的处理,默认为truel设为true时,装满时则自动清除缓冲区l设为false时,装满后则会出现异常lbuffer的值是none时将autoflush设为false是不合法的JSP简介12.1.2 JSP语法概述语法概述 指令标签指令标签/page指令指令14特制分析info属性l定义了一个通过getServletInfo方法可从servlet中检索到的串l格式为 isErrorPage属性l指明当前页是否能充当其它JSP页面的错误页。采用以下两种格式之一或者 。errorPage属性l指定一个处理当前页未被捕获的任何异常的页面

12、l格式为 这个URL指定的错误页的isErrorPage属性必须被设为true方可使用JSP简介12.1.2 JSP语法概述语法概述 指令标签指令标签/page指令指令15特制分析linclude指令指令与page指令不同,该指令应该放在你想要将外部文件插入的位置,它可以将文件整体插入到该处其格式为 Jsp文件被转换成servlet文件时,外部文件就被插入了,然后统一进行编译当外部文件发生改变时,当前页面无法得到通知,要想得知外部文件的任何改变,当前页面必须重新编译,由上一节jsp的操作过程可知,必须重新保存该jsp文件12.1.2 JSP语法概述语法概述 指令标签指令标签/include指令

13、指令JSP简介16特制分析ltaglib指令指令JSP1.1规范中新增的指定一个标记库,用于扩充标准的JSP标记集完成三个任务l首先,它通知JSP服务器,页面使用一个标记库l其次,它指定包含标记库标志符的特殊jar文件的位置l最后,它指定一个用于唯一区分这些新标记的标记前缀格式为:luri属性:一个引用标记库描述符文件(后缀名为TLD:Tag Library Descriptor)的绝对或相对URLlprefix属性:指定一个将要在TLD文件定义的标记名前面使用的前缀l如果TLD文件定义了一个名为tag1的标记,并且prefix属性的值设为test,那么实际的标记名将为test:tag112.

14、1.2 JSP语法概述语法概述 指令标签指令标签/taglib指令指令JSP简介17特制分析l动作标签动作标签一种特殊的标签,影响JSP运行时的功能格式为laction_name代表动作名称lattribute代表属性名称lvalue代表属性值分为两类lResource动作lJavaBean动作JSP简介12.1.2 JSP语法概述语法概述 动作标签动作标签18特制分析l Resource动作动作include动作标签l告诉JSP页面动态包含一个文件,即JSP页面运行时才将文件加入,例如:如果包含的是普通的文本文件,就将文件的内容发送到客户端,由客户端负责显示如果包含的是JSP文件,JSP引擎

15、就执行这个文件,然后将执行的结果发送到客户端显示如果修改了被包含的文件,那么运行时将看到修改后的结果, 这一点和include指令不同l可结合param指令,向要包含的文件传送信息,被包含的文件通过JSP的内置对象request调用getParameter方法获得参数值。格式为: JSP简介12.1.2 JSP语法概述语法概述 动作标签动作标签/Resource动作动作19特制分析forward动作标签l告诉JSP页面从该指令处停止当前页面的继续执行,而转向其他的一个页面,当前页面后边的内容将不被执行,例如:l该标签也可结合param指令,向要转到的页面传送信息,格式同include标签JSP

16、简介12.1.2 JSP语法概述语法概述 动作标签动作标签/Resource动作动作20特制分析plugin动作标签l用于插入Applet或JavaBean到JSP页面,组件必须被下载到浏览器并且在客户端执行lparam元素可以用于发送参数到Applet或JavaBean(一个可重复使用的软件组件,实际上就是一个Java类)如: prompt message 当客户访问含该段代码的JSP文件时,如果客户端不支持applet,将导致下载Java plug插件,出现客户选择是否下载插件的界面。用户下载安装后,就可以使用Java虚拟机加载执行Java applet小应用程序A.class了fallb

17、ack元素可用于指定组件失败时发送到客户端的错误信息字符串12.1.2 JSP语法概述语法概述 动作标签动作标签/Resource动作动作JSP简介21特制分析lJavaBean动作动作useBean动作标签l格式为或者l服务器将加载该bean类的一个对象setProperty动作标签l设置bean的属性getProperty动作标签l获取bean属性的值并输出12.1.2 JSP语法概述语法概述 动作标签动作标签/JavaBean动作动作JSP简介22特制分析12.1.3 JSP内置对象内置对象lJSP的内置对象的内置对象在JSP页面的脚本元素中,有些不用声明就可以使用的对象包括out、re

18、quest、response、session、application等lout对象是javax.servlet.jsp.JspWriter类的实例,JspWriter包含的方法大多数与java.io.PrintWriter类一样这个输出流对象用来向客户端输出数据,其可调用的方法如下表JSP简介23特制分析12.1.3 JSP内置对象内置对象(续续) out对象可使用的方法对象可使用的方法名称解释print(Boolean b)输出一个布尔值print(char c)输出一个字符print(double d)输出一个双精度的浮点数print(float f)输出一个单精度的浮点数print(lo

19、ng l)输出一个长整型数据print(String s)输出一个字符串newLine()输出一个换行符flush()输出缓冲区里的内容close()关闭流JSP简介24特制分析lrequest对象对象是javax.servlet.http.HttpServletRequest的实例客户每次请求页面时,JSP引擎创建一个request对象代表该请求封装了用户提交的信息,这些信息包括lHTTP请求的请求行lHTTP头l信息体调用相应的方法可以获取封装的信息,最常用的方法是request.getParameter(param_name)12.1.3 JSP内置对象内置对象(续续) request对

20、象对象JSP简介25特制分析12.1.3 JSP内置对象内置对象(续续) request对象的常用方法对象的常用方法名称解释getProtocal()获取客户向服务器提交信息使用的通讯协议getServletPath()获取JSP文件的目录getContentLength()获取提交信息的长度getMethod()获取客户提交信息的方式,例如post或getgetHeaderNames()获取头名字的一个枚举getHeader(String s)获取HTTP头文件中由s指定的属性的值,例如“content-type”,“cookie”等getRemoteHost()获取客户机的名称getRem

21、oteAddr()获取客户机的IP地址getServerName()获取服务器的名称getServerPort()获取服务器的端口号getParameterNames()获取客户提交的信息体部分中所有参数的名字getParameter(String_name)获取指定参数名字的参数值JSP简介26特制分析l response对象javax.servlet.http.httpServletResponse的实例与request对象相对应,我们可以用response对象对客户的请求做出动态响应,向客户端发送数据。类似于HTTP请求,HTTP响应也由三个基本部分组成l状态行:包括使用的协议以及状态代

22、码,表示请求是否成功l头:包含关于服务器和返回的文档的消息,例如服务器名称和文档类型等l信息体使用这个对象的一些方法可以完成如下任务l动态设置contentType属性l页面重定向l设置返回状态码等JSP简介12.1.3 JSP内置对象内置对象(续续) response对象对象27特制分析JSP简介12.1.3 JSP内置对象内置对象(续续) resnponse对象的常用方法对象的常用方法名称解释setStatus(int sc)设置返回状态码setContentType(String type) 设置被发送文档的MIME类型setHeader(String name, String valu

23、e)设置头中指定属性name为指定值valuesetRedirect(String location)重定向到指定URL 28特制分析l会话的概念会话的概念从一个客户打开浏览器连接到服务器的某个服务目录,到客户关闭浏览器离开该服务目录称为一个会话每个会话只对应于一个客户,并且可以跨多个页面lsession对象对象javax.servlet.http.HttpSession的实例,对应于会话的概念用于在使用无状态连接协议(如HTTP)的情况下跟踪关于某个客户的信息,对识别客户是非常重要的在客户首次访问某服务目录中的任何一个JSP页面时创立,并且具有一个独一无二的Id号,直到客户关闭浏览器或这个s

24、ession对象达到了最大生存时间,服务器端该客户的session对象才被取消调用相应的方法可以存储客户在访问各个页面期间提交的各种信息,比如姓名、编号等JSP简介12.1.3 JSP内置对象内置对象(续续) session对象对象29特制分析JSP简介12.1.3 JSP内置对象内置对象(续续) session对象的常用方法对象的常用方法名称解释int getMaxInactiveInterval()返回会话过期前需要经过的秒数void setMaxInactiveInterval(int interval)设置某个会话的生命期long getCreationTime()返回创建会话的时间l

25、ong getLastAccessedTime()返回上次使用此会话的时间void invalidate()使得session对象无效boolean isNew()判断是否是个新会话String getId()返回识别客户的独一无二的字符串Enumeration getIds()返回一个包含当前所有会话Id的枚举值void setAttribute(String key, Object value)在session对象中添加obj,并指定索引关键字为keyObject getAttribute(String name)从session对象获取关键字为key的对象void removeAttri

26、bute(String name)从session中删除指定索引关键字的对象Enumeration getAttributeName( )获取session对象存储的所有键名30特制分析lapplication对象对象javax.servlet.ServletContext的实例。比session对象的生存时期更长。服务器启动后,就产生了这个application对象,直到服务器关闭,该对象才被取消所有客户共享这个内置的application对象,所以任何客户对该对象中存储的数据的改变都会影响到其他客户,因此,在某些情况下,对该对象的操作需要同步处理 12.1.3 JSP内置对象内置对象(续续

27、) application对象对象JSP简介31特制分析12.1.3 JSP内置对象内置对象(续续) application对象的常用方法对象的常用方法名称解释void setAttribute(String key, Object obj)将obj对象添加到application对象中,并为obj指定一个索引关键字key。Object getAttribute(String key)获取application对象中指定关键字的对象Enumeration getAttributeNames( )返回application对象的所有索引关键字void removeAttribute(String

28、 key)删除指定索引的对象JSP简介32特制分析12.1.4 一个简单的一个简单的JSP程序程序l在表单中输入一个自然数,计算从在表单中输入一个自然数,计算从1到该数的累加和到该数的累加和%! int continuousSum(int n) int sum=0; for(int i=1;iJSP简介33特制分析12.1.4 一个简单的一个简单的JSP程序程序(续续) 计算连续和 请输入一个自然数 input type=text name=number value= 的连续和是JSP简介34特制分析12.1.4 一个简单的一个简单的JSP程序程序(续续) 例例12_1运行结果运行结果JSP简

29、介35特制分析12.2 JSP与与JavaBeanl指令标签指令标签和动作标签和动作标签都可以嵌入代码。前者实际上是将代码插入行内,后者是将另一个页面的输出插入原来的页面这些方法无助于分离表示逻辑和业务逻辑,它们都造成了显著的可伸缩性问题,不利于开发人员分工合作lJavaBean解决了这个问题,它将一系列相关的属性和方法组合在一个Java类中,构成了一个组件在JSP程序中,只要使用JavaBean动作标签调用该组件就可以了36特制分析12.2.1 JavaBean简介简介lJavaBean其实就是Java类必须使用一组相当简单而又标准的设计和命名约定,因而调用它们的应用程序无须理解其内部工作原

30、理,就可以很容易的使用JavaBean的方法JavaBean类的一个实例叫做一个bean通常我们将JavaBean文件取名为XxxBeanJSP与JavaBean37特制分析12.2.1 JavaBean简介简介(续续) JavaBean的设计要求的设计要求l对于对于JSP中使用的中使用的JavaBean,有三个设计要求,有三个设计要求必须拥有一个默认(无参数)的构造函数l如果未声明任何构造函数,默认的构造函数会被自动创建lJSP元素创建bean时,会调用默认构造函数类中不应该有公开的属性对于类内的属性,通常应该提供设置和获取其值的方法lpublic void setXxx(Objec_typ

31、e value)方法进行设置lpublic Object_type getXxx()方法进行获取,如果该属性是布尔类型的,允许使用public boolean isXxx()获取属性值l如果某个属性只有getXxx或isXxx方法 ,叫做只读属性JSP与JavaBean38特制分析l可以使用可以使用JSP脚本元素访问类的任意方法脚本元素访问类的任意方法l访问访问bean的的标准标准JSP动作动作只能使用那些遵循只能使用那些遵循getXxx/setXxx或或isXxx/setXxx命名约定的方法命名约定的方法12.2.1 JavaBean简介简介(续续)JSP对对JavaBean的访问的访问JS

32、P与JavaBean39特制分析l设计一个描述员工信息的设计一个描述员工信息的JavaBean类。包括编号、姓名、性别、工类。包括编号、姓名、性别、工资、职务属性资、职务属性package myBeans;public class EmployeeBean private int id=0,salary=0;private String name=none,occupation=none;private boolean male=true;public int getId() return id; public void setId(int id) this.id=id; public Str

33、ing getName() return name; public void setName(String name) this.name=name; public boolean isMale() return male; public void setMale(boolean male) this.male=male; public int getSalary() return salary; public void setSalary(int salary) this.salary=salary;public String getOccupation() return occupatio

34、n; public void setOccupation(String occupation)this.occupation=occupation;JSP与JavaBean12.2.1 JavaBean简介简介(续续)例例12_240特制分析lEmployeeBean类满足成为类满足成为JavaBean的条件的条件没有公开的实例变量没有声明任何显式的构造函数,从而也就拥有了一个默认的无参数的构造函数它的属性的设置和获得都使用了标准的形式JSP与JavaBean12.2.1 JavaBean简介简介(续续) 例例12_2说明说明41特制分析12.2.2 在在JSP程序中使用程序中使用JavaBe

35、anlJavaBean类在类在Web应用中的部署应用中的部署不能放在含有JSP文件的目录中,而应该放在安装servlet的目录中,且一定要使用包单个JavaBean类的字节码文件的正确位置是webAppDir/WEB-INF/classes/PackageName/含有bean类的JAR文件应该放在webAppDir/WEB-INF/lib/目录中l在在JSP页面中,可以使用三种页面中,可以使用三种JavaBean动作标签构建和操动作标签构建和操作作JavaBean组件组件useBean动作标签setProperty动作标签getProperty动作标签JSP与JavaBean42特制分析 l

36、表示建立一个表示建立一个bean类的对象类的对象class指定的bean类的类名id指定该实例的名字scope属性表示bean的有效范围,有4个可选值lPagelRequestlSessionlApplication如果已经存在scope和id相同的实例,则访问现存的实例JSP与JavaBean12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 建立建立JavaBean43特制分析lPage默认值,有效范围是当前请求访问的JSP页面表示每次请求访问JSP页面时都会创建新的bean,并将其放在PageContext对象中servlet可以通过预定义变量pageContext的g

37、etAttribute方法访问它lRequest有效范围是当前的请求将bean放在HttpServletRequest对象中,如果已经存在,则调用之,可通过getAttribute方法访问在使用jsp:include,jsp:forward,或者RequestDispatcher的include或forward方法时,两个JSP页面,或JSP页面和servlet将会共享该bean12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 建立建立JavaBeanJSP与JavaBean44特制分析lSession有效范围是客户的会话期间表示要将bean实例存储到与当前请求相关的Htt

38、pSession对象中如果这个客户在多个页面中相互链接,每个页面都包含有一个useBean标签,这些useBean标签中id的值相同,并且scope的值都是session,那么该客户在这些页面得到的bean是相同的一个lApplication表示要将bean实例存储在ServletContext中,ServletContext由Web应用中多个servlet和JSP页面共享所有客户共享这个bean,如果一个客户改变这个bean的某个属性的值,那么所有客户的这个bean的属性值都发生了变化这个bean直到服务器关闭才被取消JSP与JavaBean12.2.2 在在JSP程序中使用程序中使用Jav

39、aBean(续续) 建立建立JavaBean45特制分析 l表示读取表示读取bean属性的值属性的值bean的名称由name项指定,与useBean标签的id项对应property项指定属性名称该语法只能读取在JavaBean类文件中有getXxx方法的属性也可用JSP脚本元素得到相同的结果JSP与JavaBean12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 取得取得Bean的属性值的属性值46特制分析 l表示设置表示设置bean的属性值的属性值name项指定bean的名称,与useBean标签的id相对应property项指定属性名称value项指定属性的值该语法只能

40、设置JavaBean类文件中有setXxx方法的属性也可以用JSP脚本元素得到相同的结果JSP与JavaBean12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 设置设置Bean的属性值的属性值47特制分析l建立建立JSP文件文件Ex12_3.jsp使用上节建立的使用上节建立的EmployeeBean使用JavaBean 初始值: 名字是: 编号是: 是否男性? 工资是:元 职务是: 修改后: 名字是: 编号是: 是否男性? 工资是:元 职务是: 12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 例例12_3JSP与JavaBean48特制分析l 首先显

41、示初始值,修改后,显示新值首先显示初始值,修改后,显示新值JSP与JavaBean12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 例例12_3运行结果运行结果49特制分析l通过表单使用上节建立的通过表单使用上节建立的EmployeeBean。使用JavaBean 姓名:性别: 男 女 编号: 职务: 工资: 名字是: 编号是: 是否男性? 工资是:元 职务是: 12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 例例12_4JSP与JavaBean50特制分析12.2.2 在在JSP程序中使用程序中使用JavaBean(续续) 例例12_4运行结果运行结

42、果l在表单中填入信息后,将显示填入的信息在表单中填入信息后,将显示填入的信息JSP与JavaBean51特制分析12.3 JSP标签库标签库lJSP标签库标签库除了使用JavaBean,JSP还可以使用定制的标记,便于Web开发人员实现内容和功能的分离相对于使用JavaBean,用户自定义的标签库有如下优点lbeans不可以操纵JSP的内容,但标签库可以l使用标签比bean可以用更加简单的形式完成复杂的功能,JSP通过指令标签中的taglib指令使用标签库52特制分析12.3 JSP标签库标签库(续续)l使用自定义标签比使用使用自定义标签比使用bean要复杂一些,要复杂一些,它需要它需要3个部

43、分个部分实现标签行为的标签处理类将XML元素名称映射到标签实现上的标签库描述文件(后缀名为tld)使用标签的JSP程序JSP标签库53特制分析12.3.1 标签处理类标签处理类l标签处理类标签处理类是一个Java类,用来告诉系统在JSP程序中遇到标签后应该做些什么必须实现javax.servlet.jsp.tagext.Tag接口通常通过扩展如下两类来实现ljavax.servlet.jsp.tagext.TagSupportljavax.servlet.jsp.tagext.BodyTagSupportJSP标签库54特制分析12.3.1 标签处理类标签处理类(续续)lTagSupport类

44、及其类及其doStartTag方法方法如果在taglib指令标签中没有属性或标签体,即标签的引用形式为,这样的标签类应该扩展TagSupport类该类实现Tag接口并包含基本标签所需的大量标准功能。只须重载改该类的doStartTag方法,这个方法中的代码将在页面请求时期遇到标签头时执行为了产生输出, doStartTag方法应该调用pageContext类变量的getOut方法获得JspWriter对象除此之外,调用pageContext的别的一些方法,还可以获得和请求相关的别的数据结构:例如getRequest、getResponse、getServletContext、getSessio

45、n如果标签没有体,doStartTag方法应该返回SKIP_BODY常量,这将告诉系统忽略标签起始和结束之间的内容JSP标签库55特制分析l实现一个标签处理类,当实现一个标签处理类,当JSP程序遇到相应标签,可插入一程序遇到相应标签,可插入一个个100以内的随机整数和一行文本以内的随机整数和一行文本package tags;import javax.servlet.jsp.*;import javax.servlet.jsp.tagext.*;import java.io.*;public class ExampleTag extends TagSupportpublic int doStar

46、tTag() try JspWriter out=pageContext.getOut (); out.print(int)(Math.random ()*100); out.print( My first tag test!); catch(IOException ioe) System.out.println(Error in ExampleTag:+ioe); return(SKIP_BODY);12.3.1 标签处理类标签处理类(续续) 例例12_5JSP标签库56特制分析12.3.2 标签库描述文件标签库描述文件l标签库描述文件标签库描述文件定义了标签处理类后,接下来就是在服务器上为

47、这个类命名,并将其和一个专门的XML标签名关联起来。通过标签库描述文件可以完成这个任务该文件包括一个XML版本声明、一个DOCTYPE声明、以及一个taglib容器元素重点是taglib容器元素中的tag元素,对于没有属性的标签,tag元素又应该包括以下四个子元素lname:该元素定义了将在JSP文件中使用的tagname;ltag-class:该元素给出了标签处理类的完整类名,包括包名;lbody-content:对于没有体的标签应该取值为EMPTY;ldescription:一个简短的说明JSP标签库57特制分析l 建立一个标签库描述文件,将上例建立的标签处理类和建立一个标签库描述文件,将

48、上例建立的标签处理类和example名关联。将其存储在名关联。将其存储在Chapter12webWEB-INF tldsexample.tld 1.0 example /WEB-INF/tlds/example example tags.ExampleTag empty Insert a random integer 12.3.2 标签库描述文件标签库描述文件(续续) 例例12_6JSP标签库58特制分析12.3.3 在在JSP文件中使用标签文件中使用标签l已经有了已经有了标签处理类标签处理类和和标签库描述文件标签库描述文件,接下来就,接下来就可以在可以在JSP文件中使用自定义的标签了文件中使

49、用自定义的标签了l在首次使用标签之前,需要使用在首次使用标签之前,需要使用taglib指令标签指令标签uri属性是一个引用标签库描述符文件的绝对或相对URLprefix属性指定一个将要在标签库描述符文件定义的标签名前面使用的前缀接下来就可以使用引用标签了JSP标签库59特制分析l建立一个建立一个JSP文件,使用刚刚建立的标签处理类和标文件,使用刚刚建立的标签处理类和标签库描述文件签库描述文件使用标签12.3.3 在在JSP文件中使用标签文件中使用标签(续续) 例例12_7JSP标签库60特制分析每次按刷新后结果都是随机的每次按刷新后结果都是随机的12.3.3 在在JSP文件中使用标签文件中使用

50、标签(续续) 例例12_7运行结果运行结果JSP标签库61特制分析12.3.4 自定义标签库自定义标签库l有时我们需要在有时我们需要在JSP文件中指定标签的一些属性文件中指定标签的一些属性例如我们希望能输出1000以内,而不是100以内的随机整数这时的引用形式应该是相应的需要修改标签处理类和标签库描述文件JSP标签库62特制分析12.3.4 自定义标签库自定义标签库(续续) 修改标签处理类修改标签处理类NewExampleTag.javal使用使用attribute1将导致调用将导致调用标签处理类标签处理类的的setAttribute1方法。所以为方法。所以为了在了在Ex12_7中能够指定随机

51、整数的范围,我们为属性取名为中能够指定随机整数的范围,我们为属性取名为range,并修改标签处理类并修改标签处理类ExampleTag.java为为NewExampleTag.java如下如下public class NewExampleTag extends TagSupport protected int range=100; public int doStartTag() try JspWriter out=pageContext.getOut (); out.print(int)(Math.random ()*range); out.print( Tag test with attri

52、bute! ); catch(IOException ioe) System.out.println(Error in ExampleTag:+ioe); return(SKIP_BODY); public void setRange(String range) try this.range=Integer.parseInt (range); catch(NumberFormatException nfe) this.range=100; JSP标签库63特制分析l此外还需要修改标签库描述文件,在此外还需要修改标签库描述文件,在12.3.2节中介节中介绍的绍的tag元素中再增加元素中再增加at

53、tribute子元素,这个子元子元素,这个子元素又包括三个孙元素素又包括三个孙元素name::定义了属性名称,这个例子中,属性名为rangerequired:指出是否必须提供该属性,true是必须提供,false是可以不提供,这个例子中,range属性是可选的,如果不选,则默认为100,所以我们将其设定为falsertexprvalue:是一个可选孙元素,表示属性值是否可以是JSP表达式,以便在请求时期动态确定,默认状态下是false,表示只能是一个静态字符串12.3.4 自定义标签库自定义标签库(续续) 修改标签库描述文件修改标签库描述文件NewExample.tldJSP标签库64特制分析

54、l将刚刚建立的标签处理类和将刚刚建立的标签处理类和newexample名关联。将其存储在名关联。将其存储在Chapter12webWEB-INF tldsNewExample.tld 1.0 newexample /WEB-INF/tlds/NewExample newexample tags.NewExampleTag empty Insert a random integer within some range range false 12.3.4 自定义标签库自定义标签库(续续) 修改标签库描述文件修改标签库描述文件newexample.tldJSP标签库65特制分析l最后,我们修改例最

55、后,我们修改例12_7的的Jsp文件如下:文件如下: 使用标签 使用默认范围: 1000以内: 10000以内: 12.3.4 自定义标签库自定义标签库(续续) 修改修改JSP文件文件Ex12_7_new.jspJSP标签库66特制分析l将会出现三个不同范围内的随机数,每次刷新后结将会出现三个不同范围内的随机数,每次刷新后结果都将不同果都将不同12.3.4 自定义标签库自定义标签库(续续) Ex12_7_new.jsp运行结果运行结果JSP标签库67特制分析12.3.4 自定义标签库自定义标签库(续续)l此外我们还可以在标签中使用标签体此外我们还可以在标签中使用标签体其形式为body,body

56、里的内容可以是JSP脚本元素、指令标签、动作标签这时需要修改标签处理类ldoStartTag方法不能再返回SKIP_BODY,而应该返回EVAL_BODY_INCLUDEl如果需要在读取body内容后进行一些处理,还需要重载doEndTag方法l如果在标签内容显示完之后还想继续处理后面的页面内容,doEndTag方法应该返回EVAL_PAGES,否则应该返回SKIP_PAGEJSP标签库还可以实现嵌套标签。有兴趣的读者可以查找介绍JSP高级应用的教材JSP标签库68特制分析12.4 JSP与与ServletlJSP与与ServletJSP不过是编写Servlet的另一种不同的方式而已,JSP归

57、根到底也要转化为Servlet二者各有所长lServlet擅长数据处理,如读取并检查数据、与数据库通信lJSP擅长表示,即构建HTML来表示请求的结果通常一个大型的项目需要综合使用JSP与Servlet69特制分析l通常,我们可以将一个通常,我们可以将一个Web应用程序的结构分为三个部分应用程序的结构分为三个部分显示层(Presentation layer):包括前端的HTML、XML和Applet,主要用作用户的操作接口,负责让用户输入数据以及显示数据处理后的结果商业逻辑层(Business logic layer):负责数据处理、连接数据库、产生数据等控制层(Control layer):

58、控制整个网站的流程l这三个部分分别对应这三个部分分别对应模型模型-视图视图-控制器(控制器(Model View Controller,MVC)构架的构架的视图视图、模型模型、控制器控制器12.4.1 Web应用程序的一般结构应用程序的一般结构JSP与Servlet70特制分析SUN在JSP出现早期制定了两种规范,称为Model1和 Model212.4.1 Web应用程序的一般结构应用程序的一般结构(续续) 两种规范两种规范71特制分析lModel1设计模块:开发快速,适合于小型系统,设计模块:开发快速,适合于小型系统,其处理方式还可分为两种其处理方式还可分为两种完全使用JSP来开发l用户发

59、出一个请求到服务器端,就是由JSP页面来接收处理,接着将执行结果响应到客户端l由于JSP页面包括了大量的Java语法,程序可读性降低,不易维护,而且不利于重复利用使用JSPJavaBeanl将可重用的组件抽出来写成JavaBean,通过JSP调用JavaBean来存取数据和进行逻辑运算l依然缺乏流程控制,每个JSP文件都要完成验证参数正确性、确认用户的身份权限、异常处理等任务,因此对将来的维护造成了困难12.4.1 Web应用程序的一般结构应用程序的一般结构(续续) Model1设计模块设计模块JSP与Servlet72特制分析lModel2 MVC架构架构对于大型系统的开发,大多采取Mode

60、l2 MVC架构的开发模式MVC最主要的精神就是Model和View的分离,因而可以使网页设计师和程序员独立工作,互不影响lModel代表的是应用程序的商业逻辑(通过JavaBean、EJB等组件来实现)lView是系统的显示接口(使用JSP来输出HTML)lController提供应用程序的处理过程控制(通常是servlet)12.4.1 Web应用程序的一般结构应用程序的一般结构(续续) Model2 MVC架构架构JSP与Servlet73特制分析l使用使用Model2 MVC架构的优点架构的优点使开发流程更为明确,由Controller控制整个流程能减少本需要JSP撰写的许多条件判断逻

61、辑和流程控制的程序代码,因此便于维护目前有很多可供使用的MVC框架,由于Struts具有完整的文件,且开发源代码,因此获得了广泛的应用lModel2 MVC架构示意图架构示意图12.4.1 Web应用程序的一般结构应用程序的一般结构(续续) Model2 MVC架构架构JSP与Servlet74特制分析12.4.2 JSP与与Servlet间的信息共享间的信息共享lJSP与与Servlet间的信息共享间的信息共享在MVC方案中,由专门的servlet负责响应初始请求,这个servlet调用读取或创建数据的代码,将这些数据存放在bean中,并将请求转发到提供结果的JSP页面servlet可以将b

62、ean存储在lHttpServletRequest对象中,对应jsp:useBean动作标签的scope属性为requestlHttpSession对象中:为同一客户保存结果,对应scope为sessionlServletContext对象中:为整个Web应用保存结果,对应scope为application下面,我们以将bean存在HttpSession对象为例介绍。另外两种方式与此类似,只要改变servlet程序中setAttribute方法的执行者和useBean动作标签的scope属性就可以了JSP与Servlet75特制分析import java.io.*;import javax.s

63、ervlet.*;import javax.servlet.http.*;public class EmployeeServlet extends HttpServlet public void doGet (HttpServletRequest request,HttpServletResponse response ) throws ServletException,IOException HttpSession session=request.getSession (); myBeans.EmployeeBean bean=(myBeans.EmployeeBean)session.ge

64、tAttribute (employee); if(bean=null) bean=new myBeans.EmployeeBean(); session.setAttribute(employee,bean); String name=request.getParameter (name); String id=request.getParameter (id); bean.setName(name); bean.setId(Integer.parseInt (id); String address=/ShowEmployee.jsp; RequestDispatcher dispatche

65、r=request.getRequestDispatcher(address); dispatcher.forward(request,response); 12.4.2 JSP与与Servlet间的信息共享间的信息共享(续续) 例例12_8l利利用用例例12_2创创建建的的EmployeeBean,通通过过将将bean存存储储在在HttpSession对对 象象中中实实现现JSP与与Servlet间间的的信信息息共共享享。首首先先建建立立一一个个servlet文文件件EmployeeServlet.java,负责响应初始请求负责响应初始请求JSP与Servlet76特制分析l再建立一个再建立

66、一个 JSP文件文件ShowEmployee.jsp负责显示结果,即负责显示结果,即员工的姓名和编号员工的姓名和编号 在session中传递变量 员工姓名: 员工编号: 12.4.2 JSP与与Servlet间的信息共享间的信息共享(续续) 例例12_8JSP与Servlet77特制分析l在浏览器中输入在浏览器中输入http:/localhost:8084/Chapter12/EmployeeServlet?name=Tom&id=7,结果为:,结果为:l在浏览器中输入在浏览器中输入http:/localhost:8084/Chapter12/EmployeeServlet?name=Jerr

67、y&id=9,结果为:,结果为:12.4.2 JSP与与Servlet间的信息共享间的信息共享(续续) 例例12_8运行结果运行结果JSP与Servlet78特制分析l例例12_8说明说明首先将输入参数输入到servlet中,为一个JavaBean对象的属性进行赋值然后将这个JavaBean对象放在session中,传递给JSP页面。这样就实现了Servlet和JSP的信息共享。l如将数据存储在如将数据存储在HttpServletRequest对象中,使用语法如下对象中,使用语法如下SomeClass value=new SomeClass(.);request.setAttribute(ke

68、y,value);l如将数据存储在如将数据存储在ServletContext对象中,使用语法如下:对象中,使用语法如下:SomeClass value=new SomeClass(.);getServletContext().setAttribute(key,value);l在在JSP文件中可以通过文件中可以通过引用引用刚刚存储的对象刚刚存储的对象12.4.2 JSP与与Servlet间的信息共享间的信息共享(续续) 例例12_8说明说明JSP与Servlet79特制分析12.4.3 JSP与与Servlet间的控制传递间的控制传递lModel2 MVC通常使用通常使用Servlet来做流程控

69、制来做流程控制检查请求和设置bean需要进行大量的编程与JSP文档相比,在Servlet中更便于编程lServlet可以发送请求给可以发送请求给JSP页另一个servlet静态的HTML页。该HTML页只能使用get请求,不能使用post请求JSP与Servlet80特制分析lRequestDispatcher接口接口Servlet API中的一个接口允许将请求转交给lJSP网页lServletl将数据的输出一并加入到原来的输出流中有两种方式可获得RequestDispatcher对象RequestDispatcher rd=request.getRequestDispatcher(someU

70、RL); 或者 rd=getServletContext().getRequestDispatcher(someURL);l其中URL是相对于服务器根的URL,可以是JSP、Servlet、HTML使用forward方法将控制权完全传递给相关的URL使用include方法输出相关URL的内容JSP与Servlet12.4.3 JSP与与Servlet间的控制传递间的控制传递(续续) RequestDispatcher接口接口81特制分析lHttpServletResponse对象调用对象调用sendRedirect方法方法不能自动保留所有请求的数据将产生一个不同的最终URLlRequestDi

71、spatcher类的类的forward方法方法可以保留请求的数据保留servlet的URL12.4.3 JSP与与Servlet间的控制传递间的控制传递(续续) 两种重定向页面方法的区别两种重定向页面方法的区别JSP与Servlet82特制分析l从从JSP中发送请求到别处中发送请求到别处使用动作标签,配合 可将控制权转交给别处,并提供额外的参数其中page属性可以包含JSP表达式,使得目的地可以在请求时被计算出来 12.4.3 JSP与与Servlet间的控制传递间的控制传递(续续) 由由JSP发送请求发送请求JSP与Servlet83特制分析12.4.4 Web应用程序举例应用程序举例l例例

72、12_9 使用使用Model2 MVC架构创建一个网上书店架构创建一个网上书店两个JSP页面lShopping.jsp:显示网上书店所提供的书籍目录lCheckout.jsp: 显示用户购买的商品清单和价格一个JavaBeanlBookBean.java: 一个JavaBean,包括书名、出版社、作者、价格、购买数量一个servlet:lShoppingServlet.java:扮演流程控制的角色,具有增加购物车内容和结帐功能JSP与Servlet84特制分析lShopping.jsp为初始输入界面,显示商店所提供的书籍目录为初始输入界面,显示商店所提供的书籍目录欢迎光临网络书店网络书店 书名

73、 作者 出版社 价格 数量   12.4.4 Web应用程序举例应用程序举例(续续) Shopping.jspJSP与Servlet85特制分析 Java编程思想 侯捷 机械工业出版社 99 12.4.4 Web应用程序举例应用程序举例(续续) Shopping.jspJSP与Servlet86特制分析 Java Applet编程实例 何梅 清华大学出版社 36 12.4.4 Web应用程序举例应用程序举例(续续) Shopping.jspJSP与Servlet87特制分析 JSP基础教程 耿祥义 清华大学出版社 22 12.4.4 Web应用程序举例应用程序举例(续续) Shopp

74、ing.jspJSP与Servlet88特制分析 JSP高级开发与应用 David 科学出版社 42 12.4.4 Web应用程序举例应用程序举例(续续) Shopping.jspJSP与Servlet89特制分析l使用表单负责采集数据,并提交到指定的使用表单负责采集数据,并提交到指定的ShoppingServlet中中进行处理进行处理form和/form表单标签:用于声明表单,定义采集数据的范围,里面包含的数据将被提交到服务器表单中使用了文本框、隐藏域、提交按钮,例如ll lll12.4.4 Web应用程序举例应用程序举例(续续) Shopping.jsp说明说明JSP与Servlet90特

75、制分析lShoppingServlet.java用来控制流程用来控制流程import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;public class ShoppingServlet extends HttpServlet public void doPost(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException HttpSession session=req.g

76、etSession();Vector buyList=(Vector)session.getAttribute(shoppingcart);String action=req.getParameter(action);if(action.equals(ADD) boolean match=false; String name=req.getParameter (name); String quantity=req.getParameter (quantity); String author=req.getParameter (author); String publisher=req.getP

77、arameter (publisher); String price=req.getParameter (price); 12.4.4 Web应用程序举例应用程序举例(续续) ShoppingServlet.javaJSP与Servlet91特制分析 myBeans.BookBean bk=new myBeans.BookBean(); bk.setName(name); bk.setAuthor(author); bk.setPublisher(publisher); bk.setPrice(Float.parseFloat (price); bk.setQuantity(Integer.p

78、arseInt (quantity); if(buyList=null) buyList=new Vector(); buyList.addElement(bk); else for(int i=0;ibuyList.size();i+) myBeans.BookBean book=(myBeans.BookBean)buyList.elementAt(i); if(book.getName().equals(bk.getName() book.setQuantity(book.getQuantity()+bk.getQuantity(); buyList.setElementAt(book,

79、i); match=true; if(!match) buyList.addElement(bk); 12.4.4 Web应用程序举例应用程序举例(续续) ShoppingServlet.javaJSP与Servlet92特制分析 session.setAttribute(shoppingcart,buyList); String url=/Shopping.jsp; RequestDispatcher rd=req.getRequestDispatcher(url); rd.forward(req,res); else if(action.equals (CHECKOUT) float to

80、tal=0; for(int i=0;ibuyList.size();i+) myBeans.BookBean order=(myBeans.BookBean)buyList.elementAt(i); float price=order.getPrice(); int quantity=order.getQuantity(); total+=(price*quantity); session.setAttribute(amount,+total); String url=/Checkout.jsp; RequestDispatcher rd=req.getRequestDispatcher

81、(url); rd.forward(req,res); 12.4.4 Web应用程序举例应用程序举例(续续) ShoppingServlet.javaJSP与Servlet93特制分析lShoppingServlet从从HttpServletRequest对象中提取表对象中提取表单请求,根据请求种类不同,进入不同的处理流程单请求,根据请求种类不同,进入不同的处理流程如果action的值为”ADD”l从HttpServletRequest对象中获得书的name、author、publisher、price、quantity等信息,并以此创建一个新的BookBean类的对象l将新创建的BookBe

82、an类对象添加到了一个Vector向量对象buyList中去,需要注意的是,如果原来Vector对象中没有这本书,则单独添加一个代表这本书BookBean,如果已经存在这本书,则修改代表这本书的BookBean的quantity数量属性l将buyList存储在session对象中,属性名为Shoppingcart,使其可以在一个会话中共享l将控制流程传递给Shopping.jsp继续购物JSP与Servlet12.4.4 Web应用程序举例应用程序举例(续续) ShoppingServlet.java说明说明94特制分析如果action的值为” CHECKOUT”l从buyList依次取出每个

83、bookBean对象,根据单价数量计算出每种书的价钱,再将每种书的价钱相加得到总金额totall将total存储在session对象中,属性名为amount,使其可以在一个会话中共享l将控制流程传递给Checkout.jsp显示结帐信息JSP与Servlet12.4.4 Web应用程序举例应用程序举例(续续) ShoppingServlet.java说明说明95特制分析lBookBean.java代表书籍的相关信息代表书籍的相关信息package myBeans;public class BookBean private String name; private String author;

84、private String publisher; private float price; private int quantity; public String getName() return name; public String getAuthor() return author; public String getPublisher() return publisher; public float getPrice() return price; public int getQuantity() return quantity; public void setName(String

85、 name) try byte b=name.getBytes (ISO-8859-1); this.name=new String(b); catch(Exception e) JSP与Servlet12.4.4 Web应用程序举例应用程序举例(续续) BookBean.java96特制分析 public void setAuthor(String author) try byte b=author.getBytes (ISO-8859-1); this.author=new String(b); catch(Exception e) public void setPublisher(Str

86、ing publisher) try byte b=publisher.getBytes (ISO-8859-1); this.publisher=new String(b); catch(Exception e) public void setPrice(float price) this.price=price; public void setQuantity(int quantity) this.quantity=quantity;JSP与Servlet12.4.4 Web应用程序举例应用程序举例(续续) BookBean.java97特制分析lCheckout.jsp显示结帐信息显示结

87、帐信息结帐信息结帐信息 书名 作者 出版社 价格 数量JSP与Servlet12.4.4 Web应用程序举例应用程序举例(续续) Checkout.jsp98特制分析% Vector buyList=(Vector)session.getAttribute(shoppingcart); for(int i=0;i 12.4.4 Web应用程序举例应用程序举例(续续) Checkout.jspJSP与Servlet99特制分析总金额为:  12.4.4 Web应用程序举例应用程序举例(续续) Checkout.jspJSP与Servlet100特制分析l输出购买的每种书的信息输出购买的

88、每种书的信息从session对象中取得属性名为shoppingcart的向量对象从shoppingcart对象中依次取出购买的各种书的name、author、publisher、price、quantity等信息,并以表格的方式显示出来l输出购买的总金额输出购买的总金额从session对象中取得属性命为amount的字符串显示该字符串l通过表单显示一个通过表单显示一个“继续购物继续购物”的按钮,可将控制的按钮,可将控制流程传递给流程传递给Shopping.jsp12.4.4 Web应用程序举例应用程序举例(续续) Checkout.jsp说明说明JSP与Servlet101特制分析12.4.4

89、 Web应用程序举例应用程序举例(续续) 例例12_9运行结果运行结果JSP与Servlet102特制分析12.4.4 Web应用程序举例应用程序举例(续续) 例例12_9运行结果运行结果JSP与Servlet103特制分析12.5 本章小结本章小结l本章内容本章内容JSP的基本概念及其构成的基本语法在JSP中如何使用JavaBean在JSP中如何使用标签Web应用程序的一般结构JSP与Servlet间的信息共享和控制传递l本章要求本章要求了解JSP的运行机制和基本概念熟练掌握JSP常用的三类组件,包括脚本元素、指令标签、动作标签了解JavaBean的基本含义以及如何在JSP中使用了解JSP中使用标签的基本流程了解使用Java编写Web应用程序的两种基本模式了解JSP与Servlet间信息共享和控制传递的基本方法104特制分析

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 资格认证/考试 > 自考

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号