Struts2.0 第03章 Action_第1页
Struts2.0 第03章 Action_第2页
Struts2.0 第03章 Action_第3页
Struts2.0 第03章 Action_第4页
Struts2.0 第03章 Action_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第三章 Action在前面提到MVC模式中,需要一个控制器来负责浏览器与服务器的通讯,实现处理用户与服务器的交互。而在Struts2框架中,实现这一功能就是Action,它是整个框架的最核心部分,Action的使用反应了应用程序的功能需求,Action负责存储数据和状态,与应用的具体业务逻辑打交道。在本章中将关注如何在具体的应用中根据不同的需要实现Action,讨论Action如何提供Web应用中所需要的通用功能。除了Action接口之外,Struts2 Action也可以实现其框架中它模块的一些功能,例如校验、国际化、异常处理等等。3.1 Action简介实现Struts2框架的Action

2、有两种方案。一种是实现框架所提供的Action接口,另一种则是使用框架提供的ActionSupport基类。Struts2规定,无论使用哪种方法,在最后编写的Action类中都必须实现execute()这个方法。在Action中首先会涉及到返回类型的概念,下面就让我们来仔细分析它们。3.1.1返回类型返回类型就是Action执行完后,返回的结果字符串,根据它才能控制页面的跳转。Struts2预定义的返回类型定义在com.opensyphony.xwork2.action这个文件中,它是框架所定义的接口。下面就分析一下该文件,看看框架都预定义了哪些返回类型。com.opensyphony.xwo

3、rk2.actionpackage com.opensymphony.xwork2;public interface Action public static final String SUCCESS = "success" public static final String NONE = "none" public static final String ERROR = "error" public static final String INPUT = "input" public static final

4、String LOGIN = "login" public String execute() throws Exception;上面的代码可以从Xwork2提供的源文件里找到,这里省略了原文档的部分注释。注意:对于返回类型的含义没有强制性的要求,用户可以在控制器出错的情况下返回SUCCESS,并为之配置出错的返回页面,系统不会报错,但是出于对代码可读性和可维护性的考虑,建议读者按照返回类型的字面含义去配置它,例如Action正确执行则返回SUCCESS,出错则返回ERROR,需要返回到输入页面则返回INPUT等等。在该文件中可以发现有很多预定义的静态字符串常量,其中有非常眼

5、熟的字符串常量SUCCESS,INPUT等等,也就是上述的返回类型。接着来看看在实际的应用中如何配置返回类型。struts.xml<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC "-/Apache Software Foundation/DTD Struts Configuration 2.0/EN" "/dtds/struts-2.0.dtd"><struts&g

6、t; <constant name="struts.devMode" value="true" /> <package name="default" extends="struts-default"><!-包含默认配置文件,这样就不必对每个参数详细配置-> <interceptors><interceptor name="greeting" class="example.GreetingInterceptor">&l

7、t;/interceptor> </interceptors> <!- 使用默认的拦截器栈的配置 - -><default-interceptor-ref name="completeStack"></default-interceptor-ref><!- 配置控制器 class属性指向对应的源代码文件 - -><action name="greeting" class="example.GreetingAction"><!- 为此控制器添加对应的SU

8、CCESS返回类型,并关联一个页面 -><result name="success" type="velocity">ex01-result.vm</result><interceptor-ref name="greeting"></interceptor-ref></action> </package></struts>下面让我们来看看对应控制器的源代码。Example Actionpackage example;import com.open

9、symphony.xwork2.ActionSupport;public class Greeting extends ActionSupport public String execute() throws Exception return SUCCESS;代码中加粗的部分就是在框架中所预定义的返回类型,在Action中用到的是大写的返回类型名,而在配置文件struts.xml中用到的则是对应的小写字符串值,由这两者的一一对应关系将Action和Result一一对应起来。返回类型是沟通Action与Result的一座桥梁。3.1.2 execute()方法在Struts2中所有的Action

10、都要实现execute()方法。用户的业务逻辑就是在该方法中处理,然后通过返回类型回到对应的视图,Action的作用就相当于在前述章节中讲解Struts2改进MVC模式的派发器作用。要实现execute()方法有两种方法,一种是实现com.opensyphony.xwork2.action接口,还有一种则是从com.opensymphony.xwork2.ActionSupport基类派生。两种方法各有优劣,下面分别举例说明:n 方法一:实现Action接口我们选取了第二章的例子作演示:HelloWorld.javapackage example;import com.opensymphony

11、.xwork2.Action;public class helloworld implements Actionpublic String message;/欢迎消息public String execute()/添加欢迎消息message = “helloworldn” return SUCCESS;/*省略语句*/ 可以看出实现这样的一个接口要求很简单,同时分析上文给出的Action源文件可以发现它的功能也有局限,没有给开发者提供任何额外的功能,因此这样的实现方法比较适合简单的Action。对于稍复杂的应用应该考虑使用继承ActionSupport基类。n 方法二:继承ActionSupp

12、ort基类同样,为简单起见,我们选取了第一部分2.4.1的例子作说明:helloworld.actionpackage example;import com.opensymphony.xwork2.ActionSupport;public class helloworld extends ActionSupportpublic String message;public String name;public String execute()if ( name = null | "".equals(name)|"w".equals(name)/如果用户的输

13、入不合法,那么给出出错信息addFieldError("name","Blank names or 'w' not allowed");/返回输入页面return INPUT;/添加欢迎消息message = "hello "+name+"!n"return SUCCESS;表面上看,似乎这个Action和前一个例子没有太大的差别,都是实现了execute()方法,然后返回一个返回类型。然而注意execute()里面黑体的部分读者也许就能发现,这里ActionSupport提供了出错处理的一个函数。

14、其实远远不止这一个简单的功能,ActionSupport还提供了近30个成员函数涵盖了国际化、校验、出错处理等各个方面来处理用户的业务逻辑。所以如果用户的业务逻辑不是足够简单的话,那么应该选择从ActionSupport基类中派生出自己的Action,这样就可以使用框架所带来的种种便捷。3.2 Action接口有了上面的分析,下面让我们直接来看一下com.opensyphony.xwork2.action接口的源代码:(上面已经给出,这里为了和下面的比较,不妨再次给出)。com.opensyphony.xwork2.actionpackage com.opensymphony.xwork2;p

15、ublic interface Action public static final String SUCCESS = "success" public static final String NONE = "none" public static final String ERROR = "error" public static final String INPUT = "input" public static final String LOGIN = "login" public Str

16、ing execute() throws Exception;当从页面提交请求到一个action的时候,应用就会跳转到相应的action中去执行execute()方法。所以当编写自己的action的时候,如果是实现这个接口,那么只要在execute()方法中添加相应的功能代码就可以了,但是这并不是一个好的实现业务逻辑的方法,因为这样对于只有很少代码的应用或许是可以的,但是如果是对有比较多的代码的应用,那么必定会造成逻辑的混乱,对以后的维护、修改等都是不利的。在后面,读者将会看到,我们将会把实现代码放在相应的类中,而在action的execute()方法中只是调用这些方法,以此来达到便于管理的目

17、的。3.3 ActionSupport基类ActionSupport是编写设计业务逻辑Action的强有力支持。它提供的功能也十分强大。下面将会仔细的介绍一些常用的ActionSupport的成员函数,并且详细的了解ActionSupport的原理。下面列出了ActionSupport基类的大部分成员函数以及相关描述:表3-1 ActionSupport的成员函数返回类型成员函数描述voidaddActionError(Sting anErrorMessage)向Action添加一个Action级别的错误voidaddActionMessage(String aMessage)向Action添

18、加一个Action级别的信息void addFieldError(String fieldName, String errorMessage)为指定的域添加一个出错信息void clearErrorsAndMessages()清除所有的错误和信息Stringexecute()其缺省的实现仅返回SUCCESSCollectiongetActionErrors()获得Action级别的错误集合CollectiongetActionMessages()获得Action级别的信息集合MapgetFieldErrors()获得与域相关的错误信息的集合StringgetText(Str

19、ing aTextName)基于键获得指定的键值,不存在则返回NULLStringgetText(String aTextName, List args)基于键和附加参数获得指定的键值,不存在则返回NULLStringgetText(String aTextName, String defaultValue)基于键获得指定的键值,不存在则返回缺省值boolean hasActionErrors()是否有Action级别的错误boolean hasActionMessages()是否有Action级别的信息boolean hasErrors()是

20、否有错误,包括域和Action级别boolean hasFieldErrors()是否有域级别的错误voidpause(String result)暂停Action的执行,抛出异常,并转向对应返回类型voidsetActionErrors(Collection errorMessages)设置Action级别的所有错误voidsetActionMessages(Collection messages)设置Action级别的所有信息voidsetFieldErrors(Map errorMap)设置域级别的所有错误voidvalidate()默认的空校验器

21、我们在编写控制器的时候,能够使用的框架的API也就是这些了,当然不是所有的都经常使用,一般常用的是出错处理的一些函数,如hasErrors()、hasFieldErrors()等等。读者可以对照自己的需求合理的选取和使用自己所需的API。为了更好的理解Struts2,下面我们对ActionSupprot的源代码进行剖析:com.opensyphony.xwork2.ActionSupportpackage com.opensymphony.xwork2;/*省略代码*/public class ActionSupport implements Action,, Validateable,, V

22、alidationAware,, TextProvider,, LocaleProvider,, Serializable,, ContinuableObject protected transient static final Log LOG = LogFactory.getLog(ActionSupport.class); private transient final TextProvider textProvider = new TextProviderSupport(getClass(),, this); private final ValidationAwareSupport va

23、lidationAware = new ValidationAwareSupport(); public void setActionErrors(Collection errorMessages) validationAware.setActionErrors(errorMessages); public Collection getActionErrors() return validationAware.getActionErrors(); /*省略语句*/ public Map getErrors() return getFieldErrors(); /*省略语句*/ public L

24、ocale getLocale() return ActionContext.getContext().getLocale(); public String getText(String aTextName) return textProvider.getText(aTextName); /*省略语句*/ public void addActionError(String anErrorMessage) validationAware.addActionError(anErrorMessage); /*省略语句*/ public String doInput() throws Exceptio

25、n return INPUT; /*省略语句*/ public boolean hasActionErrors() return validationAware.hasActionErrors(); /*省略语句*/ public void clearErrorsAndMessages() validationAware.clearErrorsAndMessages(); public void validate() public void pause(String result) 从上述代码中可以发现ActionSupport基类实现了很多的接口,但是仔细的观察上面列出的函数不难发现,它所提

26、供的接口都是围绕着控制器的核心出错处理来完成的,如hasActionErrors()等等。纵观整个文件,所有的操作都围绕着validationAware这个类展开,validationAware对于ActionSupport来说是非常重要的一部分,所有的Error,Message,FieldError都间接的存放在validationAware这个类中。那么validationAware这个类究竟是什么样子的一个类呢?下面就来看看它的庐山真面目:com.opensyphony.xwork2. validationAware/*省略代码*/public class ValidationAware

27、Support implements ValidationAware, Serializable private Collection actionErrors; private Collection actionMessages; private Map fieldErrors; /*省略语句*/ 看到这里就恍然大悟了,actionErrors和actionMessages实际是用Collection这个数据结构存放的,fieldErrors则是用Map这个数据结构存放的,所有Action对这三个变量的操作实际上都是间接的对这三个数据结构的操作。以后用到这三个类的时候自然就有了经验。3.4

28、Action实例作为示例,我们在这里提供两种不同功能Action的完全实现,供读者参考和练习。n 实现Action接口;n 继承ActionSupport基类;3.4.1 实现Action接口的实例这里我们使用Action完成一个有趣的应用:由服务端动态生成颜色代码供客户端显示时使用,这样在客户端每一次刷新页面的时候,文字的颜色就改变一次。下面详细讲解如何实现该应用。为了实现这个应用,我们需要编写一个控制器、一个页面以及与之对应的配置文件,下面让我们来一步一步的完成它。web.xml<?xml version="1.0" encoding="UTF-8&qu

29、ot;?><web-app id="WebApp_9" version="2.4" xmlns=" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation=" <display-name>Struts 2 First</display-name> <filter> <filter-name>struts-cleanup</filter-name> <f

30、ilter-class> org.apache.struts2.dispatcher.ActionContextCleanUp </filter-class> </filter> <filter-mapping> <filter-name>struts-cleanup</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>struts2</filter

31、-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>in

32、dex.html</welcome-file> </welcome-file-list></web-app>这个文件是所有Web应用都要有的配置文件,但是对于不同的框架,实现的方法和语法是不尽相同的。web.xml是SUN servlet规范的标准配置文件,所有的Java的Web开发项目都要配置文件,我们发现Struts2在web.xml里面配置了filter,由此也可以看出,Struts2框架是作为一个过滤器来处理所有的Web请求的。从上面的配置文件可以看出,web.xml指定容器在捕获到Web请求之后将其转交给Struts2,那么Struts2又是如何来

33、处理这些请求的呢?这就要观察Struts2的配置文件struts.xml了。struts.xml<!DOCTYPE struts PUBLIC "-/Apache Software Foundation/DTD Struts Configuration 2.0/EN" "/dtds/struts-2.0.dtd"><struts> <constant name="struts.devMode" value="true" /> <

34、package name="ActionDemo" extends="struts-default"> <action name="colorText" class="example.ColorText"> <result name="success" type="velocity">Colorful.vm</result> </action> </package> </struts>这是Strut

35、s2的配置文件,它为Xwork2的工作方式进行配置。分析这段配置文件可以看出,URL中对colorText.action的请求会被Struts2转交给用户所编写的代码example.ColorText,具体是怎么处理的,当然就要看看对应的源代码是怎么编写的了。colorText.javapackage example;import com.opensymphony.xwork2.Action;public class ColorText implements Actionprivate String randomRGB;public String execute()int R=(int)(Ma

36、th.random()*254+1);int G=(int)(Math.random()*254+1);int B=(int)(Math.random()*254+1);randomRGB=Integer.toHexString(R)+Integer.toHexString(G)+Integer.toHexString(B);return SUCCESS;public String getRandomRGB() return randomRGB;在控制器的代码里面,首先生成了一个随机的颜色RGB,并将其组合为对应的RGB颜色的16进制代码,如果颜色生成成功,就返回成功执行的代码SUCCESS.

37、代码执行到这里,Struts2就会去配置文件struts.xml里面查找此控制的结果类型SUCCESS的配置,显然配置文件指示转向到Colorful.vm继续执行。ColorText.java就是这个应用的action,它的功能是为页面提供随机的颜色。这将会在后面的效果图中看到。Colorful.vm<html><head><title>This Page Generates Colorful Texts</title></head><body><font color="$randomRGB"&g

38、t;NanJing Food<br>/*省略正文部分*/</font></body></html>这是执行colorTest.java这个action后跳转到的页面,显示一些文本。代码中加粗的部分,就是变色页面的关键代码,通过$randomRGB每一次刷新页面都会从Action取得一个随机的颜色,从而实现了页面颜色的不断变化。由于在视图中使用了中文,必须做相应的配置(即国际化的问题,在后面将会详细介绍,这里就暂不介绍),设置对应的配置文件:perties /velocity配置文件input.encoding=GBKout

39、put.encoding=GBKSperties /Struts2配置文件Struts.i18n.encoding=GBK最后,完成的应用的文件层次结构图如下:图3-1应用的文件层次结构在文件层次结构图中出现了我们未曾提到的test文件夹,这是对Action测试时留下的,与项目本身没有关系。如果读者的配置和文件都没有错误的话,执行后应该能得到这样的一个结果:图3-2 结果页面如果读者刷新页面,那么将得到另一种颜色的文字:图3-3 刷新后的页面3.4.2 实现ActionSupport基类的实例我们知道ActionSupport基类为用户提供了很多的函数使得Action实现起来

40、更上手,下面来看这样一个例子:首先用户登陆一个页面AS.JSP,然后页面提示用户输入一个质数,如果输入的是一个质数,ACTION会跳转到成功页面,如果不是,ACTION会添加错误提示信息,并将页面重定向到输入页面。下面具体分析这些源文件。AS.jsp<% taglib uri="/struts-tags" prefix="s" %><!DOCTYPE HTML PUBLIC "-/W3C/DTD HTML 4.01 Transitional/EN"><html> <head> <t

41、itle>THIS PAGE TESTS ACTIONSUPPORT CLASS</title> </head> <body> <s:form action="prime"> <s:textfield label="Please enter a Prime Number:" name="number"/> <input type="submit"/> </s:form> </body></html>界面

42、使用了Struts2的标签会在后续章节中详细阐述,这里textfield标签是一个文本输入标签,它与常规的文本输入域相比最大的优点就是集成了错误显示功能。从页面取得输入的数据之后,需要对该数据进行一些判断,因此还需要编写对应的控制器primeAction。primeAction.javapackage example;import com.opensymphony.xwork2.ActionSupport;public class primeAction extends ActionSupportprivate int num;private String number;public Stri

43、ng execute() num=Integer.valueOf(number);if ( !IsPrimeNumber(num) addFieldError("number","You entered a non Prime");/如果不是质数那么添加出错信息,并且返回pause(INPUT);if ( IsPrimeNumber(num) return SUCCESS;return INPUT;public BooleanIsPrimeNumber(int i)/质数的判断函数int m=(int)Math.sqrt( i );for (int n=

44、2;n<=m;n+)if ( i%n=0 ) return false;return true;public String getNumber() return number;public void setNumber(String number) this.number = number;这个Action对用户输入的数据进行处理,是质数的将其转到一个成功的页面pass.html,如果不是,那么它就会向输入域添加一个域级别的错误信息,然后调用pause()方法使用户返回INPUT页面重新进行输入。pass.html<!DOCTYPE HTML PUBLIC "-/W3C/

45、DTD HTML 4.01 Transitional/EN"><html> <head> <title>Congratulations</title> </head> <body> <font color="red"> <h2>Congratulations You passed the Prime Tests</h2> </font> </body></html>这是一个简单的显示通过信息的页面。如果通过了质数测试

46、,那么系统将向用户显示这个页面。struts.xml<!DOCTYPE struts PUBLIC "-/Apache Software Foundation/DTD Struts Configuration 2.0/EN" "/dtds/struts-2.0.dtd"><struts> <constant name="struts.devMode" value="true" /><package name="Acti

47、onDemo" extends="struts-default"> <action name="prime" class="example.primeAction"> <result name="success">pass.html</result> <result name="input">AS.jsp</result> </action></package></struts>这个是

48、对应的配置文件,由于web.xml和前面所举的例子完全一致,所以这里不再累述。WEB应用的框架结构和上例也是一样的,读者可以参照前面的例子进行配置。由于篇幅的原因,我们这里只给出,输入错误后的界面。图3-4 有FieldError的INPUT页面3.5在Action中实现基本校验校验是业务逻辑中经常碰到的一个问题,有很多方法可以实现这个业务逻辑。Struts2提供了基本校验和高级的框架校验来满足不同层次的需要,这里将向读者讲述基本校验的一些策略和方法,至于高级的校验框架,将在后面的第三部分高级特性中向读者详细阐述。3.5.1使用Action的execute()方法如果我么使用Action接口,

49、而不是集成ActionSupport,因为没有框架提供的API支持所以大部分的校验逻辑都由用户自行在execute()这个方法里完成,而且无法集成出错的处理,如果要添加出错信息,那么只有在Action里面添加新的属性字段,因此比较适合一些简单的校验。例如在第一部分向读者展示的一个HelloWorld的例子,其实就是基本校验的雏形。举一个简单的例子,如果需要对用户输入的一个数值进行校验以确定它是一个素数,那么用Action我们可以这样做。primeAction.javapackage example;import com.opensymphony.xwork2.Action;public cla

50、ss primeAction implements Actionprivate int number;public int getNumber() return number;public String execute() if ( IsPrimeNumber() return SUCCESS;return INPUT;public BooleanIsPrimeNumber()/*-省略代码-*/return false;当我们把校验的逻辑混合在execute()方法里面的时候,势必会造成维护的困难,不仅如此代码的可复用性也大大降低。因此十分有必要将校验与Action的execute()方法独

51、立开来。3.5.2使用ActionSupport的validate()方法与基本的Action相比ActionSupport实现了很多的成员函数,特别是为校验提供便利的很多成员函数,不仅如此ActionSupport更是实现了validate()这个方法,将校验与业务逻辑的流程独立开来,这样ActionSupport与Action相比就更适合拿来做校验。同样的校验质数的应用如果有了ActionSupprot基类的支持,可以这样写。primeAction.javapackage example;import com.opensymphony.xwork2.ActionSupport;public

52、 class _primeAction extends ActionSupportpublic int number;public int getNumber() return number;public String execute()return SUCCESS;public void validate()/TODO how to validateif ( isPrimeNumber(number) ;addFieldError("number","You should Enter a Prime number");public Boolean is

53、PrimeNumber( int number)/TODO validate Prime numberreturn false;这样来写代码不仅对客户更友好(提供了出错的信息提示),代码的可复用性也得到了加强,因此如果不是特别简单的校验,推荐使用基类方式来完成校验。3.5.3 使用注释实现校验上面介绍了两种实现校验的方法,它们有一个共同点:所有实现校验功能的代码都是由程序员自己编写。或许有人会问:作为一个框架,Struts2在校验上只能为使用者提供这些功能吗?其实,Struts2提供的功能远不止这些,下面将介绍的注释实现校验就能在很大程度上简便校验的实现。Struts2本身提供了许多校验器供编

54、程人员使用,使用这些校验器可以方便地校验像输入是否为空、是否符合特定的格式(如:Date格式、email格式)等规则。现在,由于Java1.5的注释机制能更加方便程序员编程,所以Struts2也引入了这一机制。而在Struts2中,结合上面的两种优点,可以使用注释来实现校验功能。通过查看源代码可以发现,在包com.opensymphony.xwork2.validator.annotations下有实现校验的源代码文件,下面将这些文件列表如下3-2所示:表3-2 注释校验器及其功能文件名功能RequiredFieldValidator.java校验指定字段是否为空RequiredStringV

55、alidator.java校验指定字符串字段非空IntRangeFieldValidator.java校验指定整数字段是否在一个范围内DateRangeFieldValidator.java校验指定的日期是否在一个范围内ExpressionValidator.java校验指定的表达式是否为真FieldExpressionValidator.java校验指定OGNL表达式字段EmailValidator.java校验一个指定的字符字段如果非空是否是一个合法邮箱地址UrlValidator.java校验一个指定的字段是否是字符串并且合法VisistorFieldValidator.java将当前校

56、验推送到另一相关校验ConversionErrorFieldValidator.java校验指定字段是否发生转换错误StringLengthFieldValidator.java校验指定字段是否发生转换错误RegexFieldValidator.java校验指定使用正规表达式的字符字段DoubleRangeFieldValidator.java校验指定符点数字段是否在一个范围内在编程过程中,只要导入包com.opensymphony.xwork2.validator.annotations,就可以使用这些校验器。要使用注释实现校验,可以按照下面的步骤:1. 创建一个接口或者一个类。正如前面所说

57、,一般情况下创建继承com.opensymphony.xwork2.ActionSupport的类。2. 为类创建字段变量,并为这此变量创建getter和setter方法。3. 使用com.opensymphony.xwork2.validator.annotations.Validation注释上面创建的类,告诉Struts2将为该类使用注释校验。例如:Validation()public class AnnotationAction extends ActionSupport这样就打开了注释校验功能。4. 为setter()方法或execute()方法添加校验器。这里是实现对不同的字段使用

58、不同的校验器的地方。例一:IntRangeFieldValidator(type = ValidatorType.FIELD, min = "6", max = "10", message = "age must be between $min and $max, current value is $bar.")public void setAge(int age) this.age = age;这里是为age的setAge()方法添加校验器,添加的校验器是IntRangeFieldValidator。其中,type可以是ValidatorType.FIELD或ValidatorType.SIMPLE,min和max是被校验整数的最大值和最小值,而message是校验出错时的信息。例二:expressions = ExpressionValidator(expression = "password=confirm", message = "password must be equles to confirm. password= $p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论