设为首页 收藏本站
查看: 1166|回复: 0

[经验分享] 深入Struts 1.1——【转自】IBM DW

[复制链接]

尚未签到

发表于 2015-10-4 11:44:26 | 显示全部楼层 |阅读模式
深入Struts 1.1
Model 2的目的和MVC一样,也是利用控制器来分离模型和视图
在利用Model 2之前,我们是把所有的表示逻辑和业务逻辑都集中在一起(比如大杂烩似的JSP)
首先,控制器(ActionServlet)进行初始化工作,读取配置文件(struts-config.xml),为不同的Struts模块初始化相应的ModuleConfig对象。比如配置文件中的Action映射定义都保存在ActionConfig集合中。相应地有ControlConfig集合、FormBeanConfig集合、ForwardConfig集合和MessageResourcesConfig集合等。

Struts 1.1中所有的处理都是在特定模块环境中进行的。模块的提出主要是为了解决Struts 1.0中单配置文件的问题。
控制器接收HTTP请求,并从ActionConfig中找出对应于该请求的Action子类,如果没有对应的Action,控制器直接将请求转发给JSP或者静态页面。否则控制器将请求分发至具体Action类进行处理。

在控制器调用具体Action的execute方法之前,ActionForm对象将利用HTTP请求中的参数来填充自己(可选步骤,需要在配置文件中指定)。具体的ActionForm对象应该是ActionForm的子类对象,它其实就是一个JavaBean。此外,还可以在ActionForm类中调用validate方法来检查请求参数的合法性,并且可以返回一个包含所有错误信息的ActionErrors对象。
如果执行成功,ActionForm自动将这些参数信息以JavaBean(一般称之为form bean)的方式保存在Servlet Context中,这样它们就可以被其它Action对象或者JSP调用。

Struts将这些ActionForm的配置信息都放在FormBeanConfig集合中,通过它们Struts能够知道针对某个客户请求是否需要创建相应的ActionForm实例。

Action很简单,一般只包含一个execute方法,它负责执行相应的业务逻辑,如果需要,它也进行相应的数据检查。执行完成之后,返回一个ActionForward对象,控制器通过该ActionForward对象来进行转发工作。
我们主张将获取数据和执行业务逻辑的功能放到具体的JavaBean当中,而Action只负责完成与控制有关的功能。遵循该原则,所以在上图中我将Action对象归为控制器部分。

提示:其实在Struts 1.1中,ActionMapping的作用完全可以由ActionConfig来替代,只不过由于它是公共API的一部分以及兼容性的问题得以保留。ActionMapping通过继承ActionConfig来获得与其一致的功能,你可以等同地看待它们。同理,其它例如ActionForward与ForwardConfig的关系也是如此。

在Struts 1.1中,为了解决并行开发的问题,提出了两种解决方案:
1. 多个配置文件(web.xml)的支持
2. 模块的支持
支持多个配置文件,是指你能够为ActionServlet同时指定多个xml配置文件,文件之间以逗号分隔,例如:
  <!-- Action Servlet Configuration -->
  <servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
  <param-name>config</param-name>
  <param-value>/WEB-INF/struts-config.xml, /WEB-INF/struts-config-registration.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
  </servlet>
这种方法可以很好地解决修改冲突的问题,不同的开发人员可以在不同的配置文件中设置自己的Action、ActionForm等等(当然不是说每个开发人员都需要自己的配置文件,可以按照系统的功能模块进行划分)。但是,这里还是存在一个潜在的问题,就是可能不同的配置文件之间会产生冲突,因为在ActionServlet初始化的时候这几个文件最终还是需要合并到一起的。比如,在struts-config.xml中配置了一个名为success的<forward>,而在struts-config-registration.xml中也配置了一个同样的<forward>,那么执行起来就会产生冲突。

为了彻底解决这种冲突,Struts 1.1中引进了模块(Module)的概念。一个模块就是一个独立的子系统,你可以在其中进行任意所需的配置,同时又不必担心和其它的配置文件产生冲突。因为前面我们讲过,ActionServlet是将不同的模块信息保存在不同的ModuleConfig对象中的。要使用模块的功能,需要进行以下的准备工作:
1、为每个模块准备一个配置文件
2、配置web.xml文件,通知控制器

决定采用多个模块以后,你需要将这些信息告诉控制器,这需要在web.xml文件进行配置。下面是一个典型的多模块配置:
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>config/customer</param-name>
<param-value>/WEB-INF/struts-config-customer.xml</param-value>
</init-param>
<init-param>
<param-name>config/order</param-name>
<param-value>/WEB-INF/struts-config-order.xml</param-value>
</init-param>
其中<param-name>表示为config/XXX的形式,其中XXX为对应的模块名
3、准备各个模块所需的ActionForm、Action和JSP等资源

如何在不同模块间进行转发?有两种方法可以实现,一种就是在<forward>(全局或者本地)中定义,另外一种就是利用org.apache.struts.actions.SwitchAction。
下面就是一个全局的例子:
    ...
    <struts-config>
...
<global-forwards>
  <forward name="toModuleB"
   contextRelative="true"  
   path="/moduleB/index.do"
  redirect="true"/>   
...
</global-forwards>  
...   
    </struts-config>
可以看出,只需要在原有的path属性前加上模块名,同时将contextRelative属性置为true即可。此外,你也可以在<action>中定义一个类似的本地<forward>。
  <action-mappings>
<!-- Action mapping for profile form -->
<action path="/login"
type="com.ncu.test.LoginAction"  
name="loginForm"     
scope="request"      
input="tile.userLogin"
validate="true">     
<forward name="success" contextRelative="true" path="/moduleA/login.do"/>
</action>
  </action-mappings>
转回到缺省模块,则模块名为空。
<forward name="success" contextRelative="true" path="/login.do"/>
此外,你也可以使用org.apache.struts.actions.SwitchAction,例如:
    ...
    <action-mappings>
<action path="/toModule"
type="org.apache.struts.actions.SwitchAction"/>  
...   
    </action-mappings>  
   
ActionServlet
我们首先来了解MVC中的控制器。在Struts 1.1中缺省采用ActionServlet类来充当控制器。当然如果ActionServlet不能满足你的需求,你也可以通过继承它来实现自己的类。这可以在/WEB-INF/web.xml中来具体指定。
ActionServlet需要完成控制器所需的前端控制及转发请求等职责。
其次,ActionServlet被实现为一个专门处理HTTP请求的Servlet,它同时具有servlet的特点。
在Struts 1.1中它主要完成以下功能:
1 接收客户端请求
2 根据客户端的URI将请求映射到一个相应的Action类
3 从请求中获取数据填充Form Bean(如果需要)
4 调用Action类的execute()方法获取数据或者执行业务逻辑
5 选择正确的视图响应客户
此外,ActionServlet还负责初始化和清除应用配置信息的任务。ActionServlet的初始化工作在init方法中完成,它可以分为两个部分:初始化ActionServlet自身的一些信息以及每个模块的配置信息。前者主要通过initInternal、initOther和initServlet三个方法来完成。
我们可以在/WEB-INF/web.xml中指定具体的控制器以及初始参数。

下面列出所有被废弃的参数,相应地在web.xml文件中也不鼓励再使用。
? application
? bufferSize
? content
? debug
? factory
? formBean
? forward
? locale
? mapping
? maxFileSize
? multipartClass
? nocache
? null
? tempDir

初始化工作完成之后,ActionServlet准备接收客户请求。针对每个请求,方法process(HttpServletRequest request, HttpServletResponse response)将被调用。该方法指定具体的模块,然后调用该模块的RequestProcessor的process方法。
protected void process(HttpServletRequest request,
  HttpServletResponse response)
  throws IOException, ServletException {
RequestUtils.selectModule(request, getServletContext());        
getRequestProcessor(getModuleConfig(request)).process(request, response);
}

RequestProcessor包含了Struts控制器的所有处理逻辑。下表列出其中几个主要的方法:
方法                                  功能
processPath                      获取客户端的请求路径
processMapping                利用路径来获得相应的ActionMapping
processActionForm            初始化ActionForm(如果需要)并存入正确的scope中
processActionCreate          初始化Action
processActionPerform 调用Action的execute方法
processForwardConfig 处理Action返回的ActionForward

ActionForm
对于ActionForm你可以从以下几个方面来理解它:
1. ActionForm表示HTTP窗体中的数据,是模型和视图的中介,它负责保存视图中的数据供模型或者视图使用。Struts 1.1文档中把它比作HTTP和Action之间的防火墙,这体现了ActionForm具有的过滤保护的作用,只有通过ActionForm验证的数据才能够发送到Action处理。
2. ActionForm是与一个或多个ActionConfig关联的JavaBean,在相应的action的execute方法被调用之前,ActionForm会自动利用请求参数来填充自己(初始化属性)。
3. ActionForm是一个抽象类,你必须通过继承来实现自己的类。
ActionForm首先利用属性的getter和setter方法来实现初始化,初始化完毕后,ActionForm的validate方法被调用,来检查参数的正确性和有效性,并且可以将错误信息以ActionErrors的形式返回到输入窗体。否则,ActionForm将被作为参数传给action的execute方法以供使用。
ActionForm bean的生命周期可以设置为session(缺省)和request,当设置为session时,记得在reset方法中将所有的属性重新设置为初始值。
由于ActionForm对应于HTTP窗体,所以随着页面的增多,你的ActionForm将会急速增加。而且可能同一类型页面字段将会在不同的ActionForm中出现,并且在每个ActionForm中都存在相同的验证代码。为了解决这个问题,你可以为整个应用实现一个ActionForm或者至少一个模块对应于一个ActionForm。

但是,聚合的代价就是复用性很差,而且难维护。针对这个问题,在Struts 1.1中提出了DynaActionForm的概念。
DynaActionForm类的目的就是减少ActionForm的数目,利用它你不必创建一个个具体的ActionForm类,而是在配置文件中配置出所需的虚拟ActionForm。例如,在下表中通过指定<form-bean>的type为"org.apache.struts.action.DynaActionForm"来创建一个动态的ActionForm--loginForm。
<form-beans>
<form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm">  
  <form-property name="actionClass" type="java.lang.String"/>
  <form-property name="username" type="java.lang.String"/>
  <form-property name="password" type="java.lang.String"/>
</form-bean>
</form-beans>
动态的ActionForm的使用方法跟普通的ActionForm相同,但是要注意一点。普通的ActionForm对象需要为每个属性提供getter和setter方法,以上面的例子而言,我们需要提供getUsername() 和 setUsername()方法取得和设置username属性,同样地有一对方法用于取得和设置password属性和actionClass属性。
如果使用DynaActionForm,它将属性保存在一个HashMap类对象中,同时提供相应的get(name) 和 set(name)方法,其中参数name是要访问的属性名。例如要访问DynaActionForm中username的值,可以采用类似的代码:
String username = (String)form.get("username");
由于值存放于一个HashMap对象,所以要记得对get()方法返回的Object对象做强制性类型转换。正是由于这点区别,如果你在Action中非常频繁地使用ActionForm对象,建议还是使用普通的ActionForm对象。
在Struts 1.1中,除了DynaActionForm以外,还提供了表单输入自动验证的功能,在包org.apache.struts.validator中提供了许多有用的类,其中最常见的就是DynaValidatorForm类。
DynaValidatorForm是DynaActionForm的子类,它能够提供动态ActionForm和自动表单输入验证的功能。和使用DynaActionForm类似,你必须首先在配置文件中进行配置:
<form-beans>
<form-bean name="loginForm" type="org.apache.struts.validator.DynaValidatorForm">
  <form-property name="actionClass" type="java.lang.String"/>     
  <form-property name="username" type="java.lang.String"/>
  <form-property name="password" type="java.lang.String"/>  
</form-bean>
</form-beans>

同时要定义验证的插件:
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"  
value="/WEB-INF/validator-rules.xml,  
/WEB-INF/validation.xml"/>
  </plug-in>

其中的validator.xml和validator-rules.xml分别表示验证定义和验证规则的内容(可以合并在一起),比如针对上例中的DynaValidatorForm,我们有如下验证定义(validator.xml):
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE form-validation PUBLIC  
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"  
"http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">
<!--    Validation Rules    $Id: validation.xml-->
<form-validation>  
<!-- ========== Default Language Form Definitions ===================== -->
<formset>  
<form name="loginForm">     
  <field property="username" depends="required, minlength,maxlength">
   <arg0   key="prompt.username"/>         
   <arg1   key="${var:minlength}" name="minlength" resource="false"/>      
   <arg2   key="${var:maxlength}" name="maxlength" resource="false"/>              
   <var>               
    <var-name>maxlength</var-name>   
    <var-value>16</var-value>         
   </var>         
   <var>      
    <var-name>minlength</var-name>     
    <var-value>3</var-value>         
   </var>      
  </field>     
  <field property="password" depends="required, minlength,maxlength" bundle="alternate">         
   <arg0   key="prompt.password"/>   
   <arg1   key="${var:minlength}" name="minlength" resource="false"/>         
   <arg2   key="${var:maxlength}" name="maxlength" resource="false"/>  
   <var>              
    <var-name>maxlength</var-name>     
    <var-value>16</var-value>        
   </var>         
   <var>      
    <var-name>minlength</var-name>
    <var-value>3</var-value>      
   </var>        
  </field>   
</form>   
</formset>
</form-validation>
从上述定义中,我们可以看到对于字段username有三项验证:required, minlength, maxlength,意思是该字段不能为空,而且长度在3和16之间。而validator-rules.xml文件则可以采用Struts提供的缺省文件。注意在<form-bean>中定义的form是如何与validation.xml中的form关联起来的。最后,要启动自动验证功能,还需要将Action配置的validate属性设置为true。
<action path="/login"  
type="com.ncu.test.LoginAction"
name="loginForm"         
scope="request"         
input="tile.userLogin"validate="true">
此时,Struts将根据xml配置文件中的定义来检验表单输入,并将不符合要求的错误信息输出到页面。但是你可能会想:这个功能虽然好,可是什么检验都跑到服务器端执行,效率方面和用户易用性方面是不是有些问题?你可能会怀念起那简单的JavaScript客户端验证。
不用担心,在Struts 1.1中也支持JavaScript客户端验证。如果你选择了客户端验证,当某个表单被提交以后,Struts 1.1启动客户端验证,如果浏览器不支持JavaScript验证,则服务器端验证被启动,这种双重验证机制能够最大限度地满足各种开发者的需要。
JavaScript验证代码也是在validator-rules.xml文件中定义的。要启动客户端验证,你必须在相应的JSP文件中做如下设置:
1. 为<html:form>增加onsubmit属性
2. 设置Javascript支持

下表中列出了一JSP文件的示例代码,红字部分为Javascript验证所需代码。
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<table bgcolor="#9AFF9A" cellspacing="0" cellpadding="10" border="1" width="100%">
<tr>
<td>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr bgcolor="#696969">
  <td align="center">     
  <font color="#FFFFFF">Panel 3: Profile</font>  
  </td>
  </tr>
<tr>  
  <td><br>
  <html:errors/>  
  <html:form action="/login.do" focus="username"  >  
  <html:hidden property="actionClass"/>   
  <center>      
  <table>      
   <tr>        
   <td>UserName:</td>   
   <td><html:text property="username" size="20"/></td>
   </tr>
   <tr>  
   <td>Password:</td>   
   <td><html:password property="password" size="20"/></td>   
   </tr>  
   <tr>  
   <td colspan=2><html:submit property="submitProperty" value="Submit"/></td>     
  </table>   
  </center>  
  </html:form>
  <html:javascript formName="loginForm" dynamicJavascript="true" staticJavascript="false"/>  

<script language="Javascript1.1" src="staticJavascript.jsp"></script>  
</td>
</tr>
</table>
</td>
</tr>
</table>
其中onsubmit的值为"return validateLoginForm(this);",它的语法为:
return validate + struts-config.xml中定义的form-bean名称 + (this);
staticJavascript.jsp的内容为:
<%@ page language="java" %>
<%-- set document type to Javascript (addresses a bug in Netscape according to a web resource --%>
<%@ page contentType="application/x-javascript" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:javascript dynamicJavascript="false" staticJavascript="true"/>
如果validator-rules.xml中定义的基本验证功能不能满足你的需求,你可以自己添加所需的验证类型。

Action
我们通过继承Action类来实现具体的执行类。具体Action类的功能一般都在execute(以前是perform方法)方法中完成,其中主要涉及到以下几个方面:
1. 辅助ActionForm进行一些表单数据的检查。
2. 执行必要的业务逻辑,比如存取数据库,调用实体bean等。
3. 更新服务器端的bean数据,后续对象中可能会用到这些数据,比如在JSP中利用bean:write来获得这些数据。
4. 根据处理结果决定程序的去处,并以ActionForward对象的形式返回给ActionServlet。
提示:由于在Action和ActionForm中都可以实现验证方法,那么如何来安排它们之间的分工呢?一般来说,我们秉着MVC分离的原则,也就是视图级的验证工作放在ActionForm来完成,比如输入不能为空,email格式是否正确,利用ValidatorForm可以很轻松地完成这些工作。而与具体业务相关的验证则放入Action中,这样就可以获得最大ActionForm重用性的可能。
前面我们提到过,我们主张将业务逻辑执行分离到单独的JavaBean中,而Action只负责错误处理和流程控制。而且考虑到重用性的原因,在执行业务逻辑的JavaBean中不要引用任何与Web应用相关的对象,比如HttpServletRequest,HttpServletResponse等对象,而应该将其转化为普通的Java对象。

此外,你可能还注意到execute与perform的一个区别:execute方法简单地掷出Exception异常,而perform方法则掷出ServletException和IOException异常。这不是说Struts 1.1在异常处理功能方面弱化了,而是为了配合Struts 1.1中一个很好的功能--宣称式异常处理机制。
宣称式异常处理和EJB中的宣称式事务处理概念类似,宣称式异常处理其实就是可配置的异常处理,你可以在配置文件中指定由谁来处理Action类中掷出的某种异常。你可以按照以下步骤来完成该功能:
1. 实现org.apache.struts.action.ExceptionHandler的子类,覆盖execute方法,在该方法中处理异常并且返回一个ActionForward对象
2. 在配置文件中配置异常处理对象,你可以配置一个全局的处理类或者单独为每个Action配置处理类
下表就定义了一个全局的处理类CustomizedExceptionHandler,它被用来处理所有的异常。
<global-exceptions>
<exception
handler="com.yourcorp.CustomizedExceptionHandler"
key="global.error.message"
path="/error.jsp"   
scope="request"   
type="java.lang.Exception"/>
</global-exceptions>
其中具体的参数含义,可以参考ExceptionHandler.java源文件。

taglib
讲完了模型和控制器,接下来我们要涉及的是视图。视图的角色主要是由JSP来完成,从JSP的规范中可以看出,在视图层可以"折腾"的技术不是很多,主要的就是自定义标记库的应用。Struts 1.1在原有的四个标记库的基础上新增了两个标记库--Tiles和Nested。
其中Tiles除了替代Template的基本模板功能外,还增加了布局定义、虚拟页面定义和动态页面生成等功能。Tiles强大的模板功能能够使页面获得最大的重用性和灵活性,此外可以结合Tiles配置文件中的页面定义和Action的转发逻辑,即你可以将一个Action转发到一个在Tiles配置文件中定义的虚拟页面,从而减少页面的数量。比如,下表中的Action定义了一个转发路径,它的终点是tile.userMain,而后者是你在Tiles配置文件中定义的一个页面。
<!-- ========== Action Mapping Definitions ============================== -->
<action-mappings>  
<!-- Action mapping for profile form -->
<action path="/login"   
  type="com.ncu.test.LoginAction"      
  name="loginForm"   
  scope="request"     
  input="tile.userLogin"
  validate="true">     
  <forward name="success" path="tile.userMain"/>   
</action>
</action-mappings>
Tiles配置文件:tiles-defs.xml
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration//EN"       "http://jakarta.apache.org/struts/dtds/tiles-config.dtd">
<tiles-definitions>  
<!-- =======================================================  -->
<!-- Master definitions                                       -->
<!-- =======================================================  -->
<!-- Page layout used as root for all pages. -->
<definition name="rootLayout" path="/tiles-layouts/rootLayout.jsp">
<put name="titleString" value="CHANGE-ME"/>   
<put name="topMenu" value="/tiles-components/topMenu.jsp"/>
<put name="leftMenu" value="/tiles-components/panel1.jsp"/>  
<put name="body" value="CHANGE-ME"/>   
<put name="footer" value="/tiles-components/footer.jsp"/>
</definition>
<!-- =======================================================  -->
<!-- Page definitions      -->  
<!-- =======================================================  -->
<!-- User Login page -->
<definition name="tile.userLogin" extends="rootLayout">
<put name="titleString" value="User Login"/>  
<put name="body" value="/src/userLogin.jsp"/>
</definition>  
<!-- User Main page -->
<definition name="tile.userMain" extends="rootLayout">
<put name="titleString" value="User Main"/>  
<put name="body" value="/src/userMain.jsp"/>
</definition>
</tiles-definitions>
而Nested标记库的作用是让以上这些基本标记库能够嵌套使用,发挥更大的作用。

Commons Logging 接口
所谓的Commons Logging接口,是指将日志功能的使用与日志具体实现分开,通过配置文件来指定具体使用的日志实现。这样你就可以在Struts 1.1中通过统一的接口来使用日志功能,而不去管具体是利用的哪种日志实现,有点于类似JDBC的功能。Struts 1.1中支持的日志实现包括:Log4J,JDK Logging API, LogKit,NoOpLog和SimpleLog。
你可以按照如下的方式来使用Commons Logging接口(可以参照Struts源文中的许多类实现):
package com.foo;
// ...
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//...
public class Foo {   
// ...   
private static Log log = LogFactory.getLog(Foo.class);
// ...   
public void setBar(Bar bar) {      
  if (log.isTraceEnabled()) {         
   log.trace("Setting bar to " + bar);   
  }      
this.bar = bar;   
}
// ...
}
而开启日志功能最简单的办法就是在WEB-INF/classes目录下添加以下两个文件:
commons-logging.properties文件:
# Note: The Tiles framework now uses the commons-logging package to output different information or debug statements.
Please refer to this package documentation to enable it. The simplest way to enable logging is to create two files in
WEB-INF/classes:
# commons-logging.properties
# org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
# simplelog.properties
# # Logging detail level,
# # Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
#org.apache.commons.logging.simplelog.defaultlog=trace
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
simplelog.properties文件:
# Logging detail level,
# Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
org.apache.commons.logging.simplelog.defaultlog=fatal
这里我们采用的日志实现是SimpleLog,你可以在simplelog.properties文件指定日志明细的级别:trace,debug,info,warn,error和fatal,从trace到fatal错误级别越来越高,同时输出的日志信息也越来越少。而这些级别是和org.apache.commons.logging.log接口中的方法一一对应的。这些级别是向后包含的,也就是前面的级别包含后面级别的信息。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-122534-1-1.html 上篇帖子: 软件开发组的团队精神--- 一个程序员在IBM的开发经验 下篇帖子: IBM AIX系统硬件配置信息 查看命令----lscfg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表