Struts+Spring+Hibernate整合入門詳解

Java 5.0php

Struts 2.0.9html

Spring 2.0.6java

Hibernate 3.2.4node

                                             做者:  Liu Liu 轉載請註明出處mysql

基本概念和典型實用例子。web

1、基本概念spring

      Struts:做爲基於 MVC 模式的 Web 應用最經典框架,兩個項目Struts webwork已經集成,成爲如今的Struts2。目前的最新版本是2.0.92007-7)。sql

      Spring 是一個輕型的容器,利用它可使用一個外部 XML 配置文件方便地將對象鏈接在一塊兒。每一個對象均可以經過顯示一個 JavaBean 屬性收到一個到依賴對象的引用,留給您的簡單任務就只是在一個 XML 配置文件中把它們鏈接好。數據庫

      Hibernate 是一個純 Java 的對象關係映射和持久性框架,它容許您用 XML 配置文件把普通Java 對象映射到關係數據庫表。使用 Hibernate 可以節約大量項目開發時間,由於整個 JDBC 層都由這個框架管理。這意味着您的應用程序的數據訪問層位於 Hibernate 之上,徹底是從底層數據模型中抽象出來的。apache

      三種技術到目前已經比較成熟,並且他們都是免費的!讓咱們對三者集成進行一個初覽(簡單而不專業):

      咱們用Struts實現從Web(網頁,MVC中的View)到後臺系統的映射(WebàAction),而後由Spring管理這些Action,把它們做爲Bean和其餘對象一塊兒處理。這些Bean之間處理業務邏輯、數據、系統狀態等,且它們被Spring統一管理,爲了區分,就算大概包括MVCMC部分吧。而後須要持久化的數據由SpringHibernate之間的接口交由Hibernate處理(這個屬於持久層)。

      必須基礎:只要Java基礎,一點HTML知識、XML基礎就能夠了。本文的目的就是從零開始創建第一個Struts+Spring+Hibernate應用。即便它是最簡單的,咱們也但願初學者可以從中理解一些思想,其中也包括系統架構的設計思想。

 

2、環境搭建

      咱們堅持免費纔是硬道理,開源纔是好事情,因此咱們所有使用開源免費的工具和軟件。若是使用MyEclipse,其中的工具將有助於簡化下面演示的工程開發,但本文不用。

      所需軟件包以下表:

序號

下載地址和文件(包)名

說明

1

JDK5.0

http://java.sun.com/javase/downloads/index.jsp

JDK5.0

2

Eclipse WTP

Eclipse IDE for Java EE Developers

下載All in One,這樣不用本身下載其餘插件

包含網站開發的Eclipsev3.3,下載All in One

3

HibernateSynchronizer-3.1.9

https://sourceforge.net/project/showfiles.php?group_id=99370

幫助開發Hibernate應用的Eclipse插件

4

Hibernate3

http://sourceforge.net/project/showfiles.php?group_id=40712 à hibernate3所指示的包

Hibernate支持包

5

Spring

http://sourceforge.net/project/showfiles.php?group_id=73357

 

spring-framework-2.0.6-with-dependencies.zip

6

SpringIDE(可選)

http://springide.org/updatesite/ 包名如
springide_updatesite_2.0.1_v200707300600.zip

7

Struts

http://struts.apache.org/download.cgi

 

爲了較全的例子和文檔,建議下載
struts-2.0.9-all.zip不然只下載lib:struts-2.0.9-lib.zip

8

Tomcat

http://tomcat.apache.org

建議下載v5.5以上版本,應用服務器(支持JSP等)Apache項目之一

9

MySQL

 

Hibernate演示須要

         

 

      1、下載了eclipse之後安裝。在所安裝的目錄下有兩個子目錄pluginsfeatures,這是兩個放eclipse插件的目錄,便可以經過拷貝須要的文件到這些目錄裏面,從而給eclipse添加新的功能。

      2、將第36的包解壓,將其中的plugins目錄直接複製到eclipse安裝目錄下,選擇「所有」替換。

 

 

      3、運行eclipse,選擇一個空目錄做爲工做區(WorkSpace),啓動之後能夠看到Welcome.html的歡迎界面。如今創建新工程FileàNewàProject,在打開的New Project窗口中選擇WebàDynamic Web Project。輸入Project name,在Target Runtime一項選擇新建(New),選擇你所安裝的Apache Tomcat,在彈出窗口輸入相關信息(Tomcat安裝目錄等)。

 

      新建工程流程以下圖。

 

工程結構以下:

 

其中咱們要寫的Java代碼在Java Resource: src(之後直接稱src)下,網站根目錄內容在WebContent下,類所在根目錄是WEB-INF/classesEclipse會自動將build/classes裏面已經編譯的類同步過去。

 

WEB-INF下的lib目錄添加以下所列的jar包。 

1)這些包在下載解壓後SpringStrutsHibernatelib目錄或者dist/module目錄下面(若是不在,能夠到網上google一把。列表中mysql-*.jar包是MySQL數據庫的JDBC Driver)。也能夠把全部libdist下的jar包拷貝過來(能夠在系統複製這些jar包,而後到Eclipse裏面選中WEB-INF裏面的lib包,而後粘帖就能夠了)。但要注意全拷貝可能會存在衝突,如struts*plugin.jar等包不能引入,不然不能運行。

(2)這些Jar包是:

antlr-2.7.2.jar

cglib-nodep-2.1_3.jar

commons-beanutils-1.6.jar

commons-chain-1.1.jar

commons-collections-2.1.1.jar

commons-dbcp.jar

commons-digester.jar

commons-logging-1.0.4.jar

commons-logging-api-1.1.jar

commons-pool.jar

commons-validator-1.3.0.jar

dom4j-1.6.1.jar

el-api.jar

el-ri.jar

freemarker-2.3.8.jar

hibernate3.jar

jsf-api.jar

jta.jar

mysql-connector-java-3.0.14-production-bin.jar

ognl-2.6.11.jar

oro-2.0.8.jar

spring-hibernate3.jar

spring.jar

struts-config.xml

struts-core-1.3.5.jar

struts2-codebehind-plugin-2.0.9.jar

struts2-config-browser-plugin-2.0.9.jar

struts2-core-2.0.9.jar

struts2-jasperreports-plugin-2.0.9.jar

struts2-jfreechart-plugin-2.0.9.jar

struts2-jsf-plugin-2.0.9.jar

struts2-pell-multipart-plugin-2.0.9.jar

struts2-plexus-plugin-2.0.9.jar

struts2-sitegraph-plugin-2.0.9.jar

struts2-sitemesh-plugin-2.0.9.jar

struts2-spring-plugin-2.0.9.jar

struts2-struts1-plugin-2.0.9.jar

struts2-tiles-plugin-2.0.9.jar

tiles-api-2.0.4.jar

tiles-core-2.0.4.jar

tiles-jsp-2.0.4.jar

xwork-2.0.4.jar

3、開始工做

WebContent下創建index.jsp,創建方式如圖。

 

 

index.jsp的內容如表,咱們暫時不分析。

<%@ page contentType="text/html; charset=UTF-8" %>

<html>

  <head> <title>Example by Doer Liu@UTStarcom sz </title></head>

  <body>

    This is my JSP page. <br>

    <form name="userInfoForm" action="login.do" method="post">

    用戶名:

    <input name="username" type="text" />

    密碼:

    <input name="password" type="password">

    <input name="sub" type="submit" value="增長" />

    <input name="res" type="reset" value="重置" />

  </form>

  </body>

</html>

 

此時就能夠運行該工程,忙了這麼久,看看效果吧。

運行方式:右鍵點擊index.jsp,選擇Run/Debug AsàRun on Server,在彈出窗口中默認咱們使用的Tomcat Server,點擊finish完成。能夠看到eclipse中內嵌的瀏覽器顯示咱們的網頁。其中表單的輸入在咱們的工程中將獲得輸入數據(用戶名和密碼),這些數據會傳給咱們將要創建的Action處理。

 

 

如今來看看如何創建咱們的Action。在src下新建一個package(包)名爲action用於保存響應Web請求的Action類。在action包下新建ActionLoginActionaction.LoginAction)以下,注意類的繼承關係。

package action;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.validator.DynaValidatorForm;

import org.springframework.web.struts.ActionSupport;

 

//咱們繼承spring提供的Action衍生類org.springframework.web.struts.ActionSupport

public class LoginAction extends ActionSupport{

 

    public ActionForward execute(

             ActionMapping mapping,

             ActionForm form,

             HttpServletRequest request,

             HttpServletResponse response) {

       return mapping.findForward("success");

      

    }

}

 

可是如今index.jsp的內容怎麼和LoginAction的數據匹配呢,咱們看到LoginActionexecute方法有一個屬性ActionForm,因而咱們創建一個類forms.UserInfoForm以下,繼承ActionForm

package forms;

import org.apache.struts.action.ActionForm;

public class UserInfoForm extends ActionForm {

    private String username;

    private String password;

   

    public String getUsername() { return username; }

    public void setUsername(String username)

    { this.username = username; }

 

    public String getPassword() { return password; }

    public void setPassword(String password)

    { this.password = password; }

}

 

 

有了兩個頭,又有了保持內容的類,如今看看咱們如何用struts把他們聯繫起來吧。

如今須要在WEB-INF下創建文件struts-config.xml。其中form-beans定義了表單是如何映射的,這裏用咱們剛剛定義的forms.UserInfoForm。

<?xml version=」1.0」 encoding="ISO-8859-1"?>

<!DOCTYPE struts-config PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"         "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

 

<struts-config>

    <form-beans>

       <form-bean name="userInfoForm" type="forms.UserInfoForm"/>

    </form-beans>

   

    <action-mappings>

       <action attribute="userInfoForm" path="/login"input="/index.jsp"type="org.springframework.web.struts.DelegatingActionProxy"

              name="userInfoForm" scope="session" validate="false">

           <forward name="success" path="/success.html"/>

       </action>

    </action-mappings>

</struts-config>

 

<action-mappings>中定義了咱們的Action。它的屬性attribute指出Action的內容輸入是咱們自定義的ActionFormpathAction賦予一個路徑,input指明只接受index.jsp的輸入,<forward標籤訂義了當Action返回"success"的時候,將定向到/success.html這個網頁。 最重要的是type,它定義了這個處理這個請求的Action類,原本應該是咱們自定義的LoginAction,但咱們卻用了spring的一個Action,爲何?由於咱們要用Spring管理咱們自定義的Action。看,strutsSpring在這裏就開始鏈接起來了。

 

但還有兩個問題,StrutsSpring又是如何知道對方的存在,如何溝通呢?Spring如何知道把控制權交給咱們自定義的LoginAction呢?

咱們先來解決第一個問題,web.xmlTomcat這些應用服務器管理的,所以咱們在這裏將strutsSpring配置聯繫起來。這是整個web.xml。請看註釋。

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" id="WebApp"

    xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

 

<display-name> Struts2+Spring2+Hibernate3 simple example by Doer Liu@UTstarcom</display-name>

 <!-- filter就理解爲一些對網頁請求的過濾吧 -->

 <!-- encodingFilter是爲了處理國際化,交由Spring處理,設置爲UTF-8 -->

 <filter>

 <filter-name>encodingFilter</filter-name>

 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

 <init-param>

 <param-name>encoding</param-name>

 <param-value>UTF-8</param-value>

 </init-param>

 </filter>

 <!-- struts 是struts的filter,這個定義就將能夠將請求交給struts過濾一番了 -->

 <filter>

 <filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

 </filter>

 

<!-- 那麼哪些請求交給struts過濾呢,這裏包括 /struts2spring2hib3bydoer下和根目錄/下的全部請求-->

 <filter-mapping>

 <filter-name>struts</filter-name>

 <url-pattern>/struts2spring2hib3bydoer/*</url-pattern>

 <url-pattern>/*</url-pattern>

 </filter-mapping>

 

 <!-- 定義一個監聽器,處理整個WebContext,簡單的理解爲整個網站的上下文環境監聽器吧這個屬於Spring-->

 <listener>

  <listener-class>

   org.springframework.web.context.ContextLoaderListener

  </listener-class>

 </listener>

 

<!-- servlet定義一個servlet爲struts的ActionServlet -->

    <servlet>

       <servlet-name>doertest</servlet-name>

       <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

       <load-on-startup>1</load-on-startup>

    </servlet>

 

<!-- servlet-mapping將servlet和請求對應起來,這裏是全部*.do的請求交由上面定義的doertest處理 -->

    <servlet-mapping>

       <servlet-name>doertest</servlet-name>

       <url-pattern>*.do</url-pattern>

    </servlet-mapping>

 

<!-- 定義默認返回頁,如輸入http://127.0.0.1/那麼根目錄下的index.html或者其餘文件就被請求 -->

    <welcome-file-list>

        <welcome-file>index.html</welcome-file>

       <welcome-file>index.htm</welcome-file>

       <welcome-file>index.jsp</welcome-file>

       <welcome-file>default.html</welcome-file>

       <welcome-file>default.htm</welcome-file>

       <welcome-file>default.jsp</welcome-file>

    </welcome-file-list>

</web-app>

 

 

經過web.xml二者聯繫上了。如今它們各自還須要一些配置。

Struts在咱們的例子裏比較簡單,在build/class下面(最終會被eclipse同步到網站的WEB-INF/classes下面)創建struts.xml

<!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

 

<struts>

    <include file="struts-default.xml" />

</struts>

Spring的默認配置文件是WEB-INF/applicationContext.xml,目前其內容很簡單,咱們只是把strutsBean放進來,以下:

映射的規則:beanname屬性必須等於struts-config.xml裏面定義的actionpath屬性,class就是這個bean的類action.LoginAction

<?xml version="1.0" encoding="UTF-8"?> 

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"> 

 

<beans>

  <!-- Action Bean , 對應的部分 struts-config.xml form-bean and action-mappings -->

  <bean name="/login" class="action.LoginAction " singleton="false">

  

  </property>

  </bean>

 

</beans>

 

如今在WebContent下面創建success時重定向的目標success.html,方法和index.jsp相似,但選擇THML類型,隨便輸入內容以便測試。這時候strutsSpring就簡單的鏈接起來了。先停掉剛纔運行起來的Tomcat,從新啓動,運行index.jsp,點擊網頁中的按鈕<添加>,看看有什麼效果。

如今,然咱們簡略描述一下數據和請求的流程。

點擊<添加>index.jsp的這個表單發送的請求是login.do(<form name="userInfoForm" action="login.do" method="post">),請求被傳給後臺,生成了doertest(處理*.do的請求)集合的一個servlet,而後傳到path/loginaction,被Springorg.springframework.web.struts.DelegatingActionProxy處理,該類找到name是/login的Bean,轉交處理權,等待結果。這個Bean就是咱們的action.LoginAction。咱們的execute中返回一個forward是"success"對應的網頁,就是success.html。因此……,你已經看到了,struts和spring已經聯繫起來了。OK!

 

下面咱們須要把hibernate整合進來了,原本考慮到例子的簡單性,打算用更簡單的類,但既然用三者整合,就是要有良好的設計。咱們須要如下幾個層次的設計:表現層,業務層,持久層。表現層就是網頁;表現層和業務層之間的接口就是網頁和action的接口,由struts處理了;業務層包括業務邏輯和事務管理等,由Spring管理,咱們只是創建具體處理對象;業務層和持久層之間由數據訪問對象DAO處理,持久層交給hibernate處理。貫穿這些層的是領域對象(domain object),即表示現實世界的對象(base object),如訂單對象,人物信息對象等等。如今看看咱們須要的剩餘設計結構。

業務層:放進包service

數據訪問對象放進包dao

持久層:hibernate

領域對象:放進包bo

既然領域對象是最基本的對象,咱們就得首先創建,本例中,能夠藉助HibernateSynchronizer生成:

首先在mysql中建立表

CREATE TABLE `userinfo` (                                                                                                                                                    

            `id` int(11) primary key auto_increment,                                                                                                                                      

            `username` varchar(20) default NULL,                                                                                                                                        

            `Password` varchar(20) default NULL                                                                                                                                      

          )

 

Eclipse中,創建hibernatemap文件:右鍵點擊WEB-INF(或其餘目錄均可,後面會提到如何使用該文件),選擇newàother,在彈出窗口中選擇Hibernate Mapping File。在彈出窗口輸入url,用戶名和密碼後點擊Refresh,能夠看到你選擇的數據庫的表,選中userinfo表。輸入包bo,用來保存從數據庫提取的領域對象。在Properties中將Id generator改成native

 

 

HibernateSynchronizer將在WEB-INF下生成Uerinfo.hbm.xml文件。

 

右鍵點擊該文件,選擇Hibernate SynchronizeràSynchronize Files。將自動生成bo.base.BaseUserinfobo.Userinfo類。這兩個就是領域對象。工具正好啊!

 

 

如今bo包裏面的對象自動生成了。

下面創建dao包中對象dao.UserinfoDAO

package dao;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import bo.Userinfo;

//從HibernateDaoSupport繼承,從而可使用getHibernateTemplate().save保存數據。

public class UserinfoDAO extends HibernateDaoSupport {

 

    public void save(Userinfo userinfo) {

       System.out.println("saved!");

       getHibernateTemplate().save(userinfo);

    }

 

}

 

再創建service包中的業務對象,service.UserinfoService

package service;

import dao.UserinfoDAO;

import bo.Userinfo;

package service;

public class LoginService {

    private UserinfoDAO userinfoDAO;

 

    public UserinfoDAO getUserinfoDAO() {

       System.out.println("shit");

       return userinfoDAO;

    }

 

    public void setUserinfoDAO(UserinfoDAO userinfoDAO) {

       System.out.println("LoginService:setAdminDAO");

       this.userinfoDAO = userinfoDAO;

    }

 

    public void saveinfo(Userinfo userinfo) {

         //進行相關業務處理,好比validate之類的。

       userinfoDAO.save(userinfo);

    }

}

 

好了,全部咱們應該創建的對象都生成了,如今把hibernate整合進來再進行一些後續處理。

首先,在applicationContext.xml文件中加入必需的Bean定義,成爲以下內容,注意其中註釋。

<?xml version="1.0" encoding="UTF-8"?> 

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"> 

 

<beans>

  <!-- Action Bean , 對應的部分 struts-config.xml form-bean and action-mappings -->

  <bean name="/login" class="action.LoginAction" singleton="false">

  <!-- property是該bean的屬性,以下面的property,在類LoginAction 中必有字段定義LoginService loginService;和getLoginService()以及setLoginService方法-->

  <property name="loginService">

    <ref bean="loginService" />

  </property>

 

  </bean>

 

 <!-- 定義DBCP的數據庫鏈接屬性,該數據源會被hibernate使用,DBCP是鏈接池開源包,其中的url,username,password須要替換成你的數據庫訪問屬性 -->

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

  <property name="driverClassName">

   <value>com.mysql.jdbc.Driver</value>

  </property>

  <property name="url">

   <value>jdbc:mysql://localhost/mysql</value>

  </property>

  <property name="username">

   <value>root</value>

  </property>

  <property name="password">

   <value>doerliu</value>

  </property>

 </bean>

 

 <!-- 配置sessionFactory, 爲Hibernate配置屬性  -->

 <bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

  <property name="dataSource">

   <ref local="dataSource" />

  </property>

  <property name="mappingResources">

   <list>

    <!—Hibernate的map 文件在這裏配置了,注意文件的相對位置。 -->

    <value>../Userinfo.hbm.xml</value>

   </list>

  </property>

  <property name="hibernateProperties">

   <props>

    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

    <prop key="hibernate.show_sql">true</prop>

   </props>

  </property>

 </bean>

 

 <!-- 業務層的事務管理由該bean管理-->

 <bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">

  <property name="sessionFactory">

   <ref local="sessionFactory" />

  </property>

 </bean>

 

 <!-- 事務處理環境(代理)配置,爲業務處理LoginService定義一個事務處理*****-->

 <bean id="userDAOProxy"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

  <property name="transactionManager">

   <ref bean="transactionManager" />

  </property>

  <property name="target">

   <ref local="loginService" />

  </property>

  <property name="transactionAttributes">

   <props>

    <prop key="save*">PROPAGATION_REQUIRED</prop>

    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>

    <prop key="is*">PROPAGATION_REQUIRED,readOnly</prop>

   </props>

  </property>

 </bean>

 

 <!-- 業務處理Bean定義 -->

 <bean id="loginService" class="service.LoginService">

  <property name="userinfoDAO">

   <ref bean="userinfoDAO" />

  </property>

 </bean>

 

 <!-- 數據訪問對象的Bean -->

 <bean id="userinfoDAO" class="dao.UserinfoDAO">

  <property name="sessionFactory"><ref local="sessionFactory"/></property>

 </bean>

 

</beans>

 

最後,LoginAction能夠處理請求並和業務層進行交流了。所以須要增長實質性內容:

package action;

 

/* @sample for training.

 * @author doer.liu@utstarcom

 * @date 2007-7-30

 */

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.springframework.web.struts.ActionSupport;

 

import bo.Userinfo;

 

import forms.UserInfoForm;

 

import service.LoginService;

 

//咱們繼承spring提供的Action衍生類org.springframework.web.struts.ActionSupport

public class LoginAction extends ActionSupport {

 

      LoginService loginService;

 

      public ActionForward execute(ActionMapping mapping, ActionForm form,

                 HttpServletRequest request, HttpServletResponse response) {

           UserInfoForm userInfoForm = (UserInfoForm) form;

           String username = userInfoForm.getUsername();

           String password = userInfoForm.getPassword();

           Userinfo userinfo = new Userinfo();

           userinfo.setUsername(username);

           userinfo.setPassword(password);

           loginService.saveinfo(userinfo);// 保存前臺的數據,插入數據庫

 

           return mapping.findForward("success"); //返回頁。

 

      }

 

      public LoginService getLoginService() {

           return loginService;

      }

 

      public void setLoginService(LoginService loginService) {

           System.out.println("setLoginService=" + loginService);

           this.loginService = loginService;

      }

}

 

Ok!整個流程到此就走通了。運行看看吧。還有什麼說的呢,動手開始吧,在此基礎上不斷修改測試,再參考相關文檔,一切都將愈來愈簡單!——有問題,看日誌!

    附件是導出的WAR文件,其中lib已被清空,只要加入文中列出的lib文件便可運行(能夠將WAR導入eclipse,或者將war文件放到Tomcat的webaspps下)http://dl2.csdn.net/down4/20070806/06111224839.war

 

      固然這個例子爲了清晰起見,在各類模式,java編程習慣上是不合適的,好比應該面向接口編程,而不是通通拿類,拿對象來處理。應該定義如ILoginService, ILoginDAO等接口,使得系統更靈活,更易移植。固然爲了說明,咱們這樣作是能夠原諒的,但工做中切記不要只圖簡單!不然還不如不用這種高級優秀的構架,由於你一用就把它破壞殆盡了。

相關文章
相關標籤/搜索