亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Spring,Django,Rails,Express這些框架技術(shù)解決的問(wèn)題

Original 2016-11-01 14:14:22 856
abstract:分別列舉了Java,Python,Ruby,Node.js的一些熱門框架,初學(xué)編程,發(fā)現(xiàn)這個(gè)世界里有各種各樣的編程語(yǔ)言和五花八門的框架技術(shù)歸納題主的問(wèn)題:這個(gè)世界上有各種各樣的框架,設(shè)計(jì)這些五花八門框架的初衷到底是什么?我們?cè)摬辉搶W(xué)習(xí)框架,該如何學(xué)習(xí)使用這些框架?回答題主的問(wèn)題:一、首先,到底什么是框架?想要回答這個(gè)問(wèn)題,我們要慢慢來(lái)。①首先從DRY原則開(kāi)始說(shuō)起Don't Repeat Y

分別列舉了Java,Python,Ruby,Node.js的一些熱門框架,初學(xué)編程,發(fā)現(xiàn)這個(gè)世界里有各種各樣的編程語(yǔ)言和五花八門的框架技術(shù)

歸納題主的問(wèn)題:

這個(gè)世界上有各種各樣的框架,設(shè)計(jì)這些五花八門框架的初衷到底是什么?我們?cè)摬辉搶W(xué)習(xí)框架,該如何學(xué)習(xí)使用這些框架?


回答題主的問(wèn)題:

一、首先,到底什么是框架?

想要回答這個(gè)問(wèn)題,我們要慢慢來(lái)。



首先從DRY原則開(kāi)始說(shuō)起

Don't Repeat Yourself,不要重復(fù)你的代碼。

DRY原則的重要性怎么提都不過(guò)分,很多人說(shuō)編程是種機(jī)械性的工作,而有很多程序員也自嘲為碼農(nóng),意為編程成了一種沒(méi)有技術(shù)含量的體力性工作。如果不想淪為這個(gè)境界,首先需要的就是將DRY原則融入你的血液,在今后的編碼工作中加以運(yùn)用。


1)最初級(jí)的DRY:語(yǔ)法級(jí)別

System.out.println(1);
System.out.println(2);
……
System.out.println(10);

我想只要學(xué)過(guò)基礎(chǔ)語(yǔ)法,都會(huì)采用下面的形式。

for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}

如果發(fā)現(xiàn)有任何人采用上面一種形式的編碼形式,那么不用懷疑,他對(duì)于編程絕對(duì)還沒(méi)有入門。

我們當(dāng)然會(huì)選擇省力的做法,這種做法不但省力,還會(huì)有利于我們后續(xù)修改或擴(kuò)展這組代碼,如:

for (int i = 1; i <= 10; i++) {
    System.out.println(i * 2 + 1);
}

我們進(jìn)行這樣的修改,只需要修改一處,而上面的形式卻需要修改10處,當(dāng)然會(huì)更麻煩且更容易出錯(cuò),所以請(qǐng)記住能不重復(fù)就不重復(fù)。


2)進(jìn)階的DRY原則:方法級(jí)別

當(dāng)我們經(jīng)常寫一些重復(fù)性代碼時(shí),我們就要注意看能否將其抽取出來(lái)成為一個(gè)方法,如:

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

讓我們將其抽取到一個(gè)方法 threadSleep() 中,這樣我們只需要調(diào)用 threadSleep() 就可以實(shí)現(xiàn)原來(lái)的功能,不但所需敲擊的代碼更少,而且代碼看起來(lái)更加清楚明白。而為了增加這個(gè)方法的復(fù)用性,我們還可以將其中固定的數(shù)字抽取成為參數(shù),如:

private static void threadSleep(int millis) {
    try {
        Thread.sleep(millis);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

這樣我們就可以利用這個(gè)方法實(shí)現(xiàn)不同時(shí)間的sleep了。要注意提高代碼的復(fù)用性也是實(shí)踐DRY原則的一個(gè)重要方法,在后面我們也可以看到框架為了提高所謂的靈活性進(jìn)行的一些設(shè)計(jì),如在適當(dāng)?shù)奈恢迷黾訑U(kuò)展點(diǎn)。


3)繼續(xù)進(jìn)階的DRY原則:類型級(jí)別

現(xiàn)在我們看一個(gè)類

public class Person {
    private String name;
    private int age;
    // Setter & Getter ...
}

我們新建一些Person類實(shí)例,并進(jìn)行一些操作:

Person person = new Person();
person.setName("jack");
person.setAge(18);
Person person2 = new Person();
person2.setName("rose");
person2.setAge(17);
.....
System.out.printf("Name: %s, Age:%d\n", person.getName(), person.getAge());
System.out.printf("Name: %s, Age:%d\n", person2.getName(), person2.getAge());
.....

觀察這些代碼,其實(shí)有很大的DRY改造空間,首先可以添加一個(gè)構(gòu)造方法

public Person(String name, int age) {
    this.name = name;
    this.age = age;
}

其次,可以添加一個(gè)toString()方法

public String toString() {
    return String.format("Name: %s, Age: %d", name, age);
}

這樣的話,上面的代碼就可以改成下面的形式。

Person person = new Person("jack", 18);
Person person2 = new Person("rose", 17);
......
System.out.println(person.toString());
System.out.println(person2.toString());
......

4)繼續(xù)繼續(xù)進(jìn)階的DRY原則:多個(gè)類組合級(jí)別

上面的代碼我們其實(shí)還是有改善空間,就是利用容器類

List<Person> list = new ArrayList<>();
list.add(new Person("jack", 18));
list.add(new Person("rose", 17));
......
list.forEach(p -> System.out.println(p));

這里利用JDK8的Stream API以及Lambda表達(dá)式輸出,其實(shí)可以進(jìn)一步簡(jiǎn)化為

list.forEach(System.out::println);

這里我們可以看到,基本上我們寫代碼只寫有變化的代碼,而盡量不寫機(jī)械性重復(fù)性的代碼,其實(shí)后面我們就會(huì)知道,這就叫專注于業(yè)務(wù)邏輯,所謂業(yè)務(wù)邏輯就是你這個(gè)項(xiàng)目中,與別的項(xiàng)目都不一樣的地方,必須由你親自去編寫實(shí)現(xiàn)的部分。

其實(shí)容器類很大程度上也是為了幫助我們編寫代碼而被設(shè)計(jì)出來(lái)的,首先讓我們不必為每一個(gè)對(duì)象起名字(省去了person,person2,...等變量),然后又為批量操作提供了可能性。像是這樣一系列有用的類組合起來(lái)可以稱之為類庫(kù)。常用的類庫(kù)有Commons-Lang包等,為我們提供了一大批實(shí)用方法,我之所以提到類庫(kù),也是因?yàn)榭蚣芷鋵?shí)也是一種特殊的類庫(kù),但是卻與一般的類庫(kù)有著本質(zhì)的不同。



設(shè)計(jì)模式,更高層級(jí)的DRY應(yīng)用

上面我講到了DRY原則的幾個(gè)層次,一般情況下大家也早就這樣使用了,屬于入門之后很容易自己就想到得一些層次。但是設(shè)計(jì)模式不一樣,設(shè)計(jì)模式是經(jīng)過(guò)長(zhǎng)時(shí)間編碼之后,經(jīng)過(guò)系統(tǒng)性的總結(jié)所提出的針對(duì)某一類問(wèn)題的最佳解決方案,又稱之為最佳實(shí)踐。

而在小規(guī)模的編碼工作中,其實(shí)并不需要什么設(shè)計(jì)模式,只有大型程序才有設(shè)計(jì)模式發(fā)揮的空間,所以我們需要借助一些特定領(lǐng)域有足夠規(guī)模的問(wèn)題來(lái)了解一下設(shè)計(jì)模式存在的必要性。


1)連接數(shù)據(jù)庫(kù),進(jìn)行一些操作,并安全釋放數(shù)據(jù)庫(kù)連接。

public static boolean updatePassword(String username, String password, String newpassword) {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    boolean success = false;
    try {
        conn = beginTransaction();
        stmt = conn.prepareStatement("select id, password from user where username = ?");
        stmt.setString(1, username);
        rs = stmt.executeQuery();
        if (rs.next()) {
            if (rs.getString("password").equals(password)) {
                PreparedStatement stmt2 = null;
                try {
                    stmt2 = conn.prepareStatement("update user set password = ? where id = ?");
                    stmt2.setString(1, newpassword);
                    stmt2.setLong(2, rs.getLong("id"));
                    success = stmt2.executeUpdate() > 0;
                } finally {
                    safeClose(stmt2);
                }
            }
        }
        commitTransaction(conn);
        return success;
    } catch (SQLException e) {
        rollbackTransaction(conn);
        throw new RuntimeException(e);
    } finally {
        safeClose(rs);
        safeClose(stmt);
        safeClose(conn);
    }
}

上面是一個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù)事務(wù),雖然只有一個(gè)查詢和一個(gè)更新,但是想要將其繼續(xù)簡(jiǎn)化卻并不容易,雖然其中有關(guān)于業(yè)務(wù)邏輯的部分只是少量幾行代碼,但是初始化,異常,提交,回滾操作讓我們很難抽取出一個(gè)合適的方法來(lái)。雖然我們已經(jīng)抽取出了 begin,commit,rollback,safeClose等方法,但是仍嫌繁瑣。

我們發(fā)現(xiàn)之所以我們難以抽取方法,主要是因?yàn)榱鞒?,因?yàn)槔锩鏍砍兜搅鞒炭刂?,而流程控制一般是由我們程序員來(lái)控制的,所以也就必然需要我們手動(dòng)編碼來(lái)完成。難道真的就不能繼續(xù)簡(jiǎn)化了嗎?這就是需要設(shè)計(jì)模式的時(shí)候了。


2)應(yīng)用設(shè)計(jì)模式「模板方法模式」

public static boolean updatePassword(String username, String password, String newpassword) {
    return connection(conn -> statement(conn, "select id, password from user where username = ?", stmt -> {
        stmt.setString(1, username);
        return resultSet(stmt, rs -> {
            if (rs.next()) {
                if (rs.getString("password").equals(password)) {
                    long id = rs.getLong("id");
                    return statement(conn, "update user set password = ? where id = ?", stmt2 -> {
                        stmt2.setString(1, newpassword);
                        stmt2.setLong(2, id);
                        return stmt2.executeUpdate() == 1;
                    });
                }
            }
            return false;
        });
    }));
}

可以看到,所有的conn,stmt,rs的開(kāi)啟和關(guān)閉,事務(wù)的提交和回滾都不用自己手動(dòng)編寫代碼進(jìn)行操作了,之所以可以達(dá)到這個(gè)效果,就是因?yàn)槭褂昧四0宸椒ㄔO(shè)計(jì)模式,核心就是通過(guò)回調(diào)方法傳遞想對(duì)資源進(jìn)行的操作,然后將控制權(quán)交給另一個(gè)方法,讓這個(gè)方法掌握流程控制,然后適當(dāng)?shù)臅r(shí)候回調(diào)我們的代碼(也就是我們自己寫的業(yè)務(wù)邏輯相關(guān)的代碼)。

這是需要額外寫的幾個(gè)方法

public interface ConnectionCallback<T> {
    T doConnection(Connection conn) throws SQLException;
}
public interface StatementCallback<T> {
    T doStatement(PreparedStatement stmt) throws SQLException;
}
public interface ResultSetCallback<T> {
    T doResultSet(ResultSet rs) throws SQLException;
}
public static <T> T connection(ConnectionCallback<T> callback) {
    Connection conn = null;
    T result = null;
    try {
        conn = beginTransaction();
        result = callback.doConnection(conn);
        commitTransaction(conn);
    } catch (SQLException e) {
        rollbackTransaction(conn);
        throw new RuntimeException(e);
    } finally {
        safeClose(conn);
    }
    return result;
}
public static <T> T statement(Connection conn, String sql, StatementCallback<T> callback) throws SQLException {
    PreparedStatement stmt = null;
    T result = null;
    try {
        stmt = conn.prepareStatement(sql);
        result = callback.doStatement(stmt);
    } finally {
        safeClose(stmt);
    }
    return result;
}
public static <T> T resultSet(PreparedStatement stmt, ResultSetCallback<T> callback) throws SQLException {
    ResultSet rs = null;
    T result = null;
    try {
        rs = stmt.executeQuery();
        result = callback.doResultSet(rs);
    } finally {
        safeClose(rs);
    }
    return result;
}

你們可能會(huì)疑惑,這些代碼加上我們寫的業(yè)務(wù)邏輯的代碼,比原來(lái)的代碼還要長(zhǎng),有什么必要使用這個(gè)設(shè)計(jì)模式。這正是我前面已經(jīng)指出的一個(gè)問(wèn)題,那就是要你的程序規(guī)模足夠大才有必要應(yīng)用設(shè)計(jì)模式,試想如果你有上百個(gè)乃至上千個(gè)數(shù)據(jù)庫(kù)操作方法需要寫,那么是不是寫這幾個(gè)額外的方法,就不算什么了呢。

其實(shí)這正是DRY原則在更高層次上的應(yīng)用,即結(jié)合設(shè)計(jì)模式來(lái)達(dá)到更高層次的代碼復(fù)用效果,進(jìn)而應(yīng)用DRY原則。而想要在這個(gè)層次繼續(xù)向上攀升,那就必須是結(jié)合眾多設(shè)計(jì)模式以及一些高層架構(gòu)設(shè)計(jì),能夠幫助我們實(shí)現(xiàn)這一目的的就是框架。


3)框架,是設(shè)計(jì)模式的集大成者,是DRY原則的最高應(yīng)用

先讓我們來(lái)看一下,使用框架會(huì)是什么樣的一種體驗(yàn)?

這里以Hibernate + Spring聲明式事務(wù)為例

@Transactional
public boolean updatePassword(String username, String password, String newpassword) {
    User user = (User) session().createQuery("from User where username = :username")
            .setString("username", username)
            .uniqueResult();
    if (user != null && user.getPassword().equals(password)) {
        user.setPassword(newpassword);
        return true;
    }
    return false;
}

可以發(fā)現(xiàn)令人驚訝的簡(jiǎn)潔,而且代碼邏輯異常清晰,完全不需要考慮conn,stmt,rs等資源的釋放,以及事務(wù)的提交和回滾,但是這些事情其實(shí)框架已經(jīng)默默的幫我們做到了。這才叫真正的專注于業(yè)務(wù)邏輯,盡最大可能的只寫與業(yè)務(wù)邏輯有關(guān)的代碼。

當(dāng)然這些框架的效果雖然神奇,其實(shí)只要細(xì)細(xì)探究其內(nèi)部原理,是完全可以理解并掌握的。


二、那么問(wèn)題就來(lái)了,框架到底是什么?要不要學(xué),怎么學(xué)?

上面我說(shuō)過(guò)了,框架其實(shí)就是一個(gè)或一組特殊的類庫(kù),特殊在什么地方?特殊在控制權(quán)轉(zhuǎn)移!

框架與一般類庫(kù)不同的地方是,我們調(diào)用類庫(kù),而框架調(diào)用我們。也就是說(shuō)框架掌握整個(gè)程序的控制權(quán),我們必須一定程度上把程序流程的控制權(quán)交給框架,這樣框架才能更好的幫助我們。

下面以JavaWeb開(kāi)發(fā)為例再進(jìn)行一些說(shuō)明,并順便簡(jiǎn)單介紹一下JavaWeb的一些脈絡(luò)。



靜態(tài)網(wǎng)頁(yè)時(shí)代

本來(lái)網(wǎng)站都是一個(gè)個(gè)靜態(tài)HTML組成的,或許這些網(wǎng)頁(yè)還是用Dreamweaver寫的,但是這樣的靜態(tài)頁(yè)面顯然不能滿足我們,很快我們就迎來(lái)了動(dòng)態(tài)網(wǎng)頁(yè)的時(shí)代。



Servlet時(shí)代

如果熟悉HTTP協(xié)議的話,我們就知道其實(shí)訪問(wèn)網(wǎng)頁(yè)的過(guò)程不過(guò)是一次TCP連接罷了。瀏覽器發(fā)起TCP連接到服務(wù)器,服務(wù)器接受請(qǐng)求,然后返回HTML代碼作為響應(yīng)。那么我們完全可以等到接受到請(qǐng)求之后,再動(dòng)態(tài)生成HTML代碼返回給客戶端。

Servlet就是這么做的,其主要代碼不過(guò)是利用out.write()一點(diǎn)一點(diǎn)的輸出HTML代碼罷了。當(dāng)然我們可以在其中摻雜一點(diǎn)動(dòng)態(tài)的東西,如返回當(dāng)前的時(shí)間。

out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<title>Index Page</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("Hello, " + new Date() + "\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");

③ JSP包打天下的時(shí)代

純粹的Servlet很是丑陋,給前端程序員理解和修改這樣的代碼帶來(lái)了很多困難。因此JSP技術(shù)被發(fā)明了出來(lái),原理也不復(fù)雜,就是不直接寫Servlet,而是先寫好JSP文件,再由服務(wù)器將JSP文件編譯成Servlet。而JSP中是以常見(jiàn)的HTML標(biāo)簽為主,這樣前端程序員就能方便的修改這些代碼了。

<!DOCTYPE html>
<html>
<head>
<title>Index Page</title>
</head>
<body>
Hello, <%=new Date()%>
</body>
</html>

PS:由只使用 Servlet到使用JSP,雖然是一個(gè)簡(jiǎn)單的變化,但這迎合了前后端專業(yè)分工的大趨勢(shì),讓前段人員只需要懂得HTML/CSS/JavaScrip代碼就可以開(kāi)始工作,而不需要學(xué)習(xí)Servlet那枯燥無(wú)味的用法,因此借著JSP技術(shù)的東風(fēng),JavaWeb技術(shù)迅速的擴(kuò)展開(kāi)來(lái)了。


④ Servlet + JSP 時(shí)代

隨著JSP技術(shù)的發(fā)展,用它寫成的網(wǎng)站也越來(lái)越大,業(yè)務(wù)邏輯也越來(lái)越復(fù)雜。開(kāi)發(fā)人員漸漸發(fā)現(xiàn)整個(gè)網(wǎng)站漸漸的再次變成了一團(tuán)亂麻,不僅僅是JSP中夾雜了大量的Java代碼,頁(yè)面之間的耦合關(guān)系也越來(lái)越緊密。

即便是要修改一個(gè)簡(jiǎn)單的按鈕文本,或者是引入一段靜態(tài)的內(nèi)容,也需要打開(kāi)越來(lái)越龐大的JSP頁(yè)面,艱難到找到需要修改的部分,有時(shí)還不僅僅是一處,這種修改是有很大的風(fēng)險(xiǎn)的,完全有可能引入新的錯(cuò)誤。

這時(shí)候開(kāi)發(fā)者漸漸意識(shí)到,僅僅使用JSP是不行的,JSP承擔(dān)了太多的責(zé)任。這時(shí)人們又想起了Servlet,Servlet中主要使用Java代碼,處理業(yè)務(wù)邏輯非常輕松。如果JSP只使用HTML代碼,而將業(yè)務(wù)邏輯的代碼轉(zhuǎn)移到Servlet中,就可以大大的減輕JSP的負(fù)擔(dān),并且讓前后端分工更加明確。



MVC模式時(shí)代


Servlet + JSP模式的基礎(chǔ)上,Java陣營(yíng)進(jìn)一步發(fā)展出了一種適合JavaWeb應(yīng)用的設(shè)計(jì)模式,MVC設(shè)計(jì)模式,即將程序分為顯示層(Viewer),控制層(Controller),模型層(Model)。如下圖所示:

QQ圖片20161101114531.png

一次典型的訪問(wèn)是這樣的流程:

1. 用戶輸入網(wǎng)址或點(diǎn)擊鏈接或提交表單,瀏覽器發(fā)起請(qǐng)求

2. --> 通過(guò)互聯(lián)網(wǎng),通過(guò)HTTP協(xié)議 -->

3. Tomcat接受到HTTP請(qǐng)求,生成HttpServletRequest對(duì)象,根據(jù)Web.xml的配置,調(diào)用開(kāi)發(fā)者編寫的HttpServlet,HttpServlet根據(jù)請(qǐng)求內(nèi)容,調(diào)用JavaBean獲取數(shù)據(jù),JavaBean從數(shù)據(jù)庫(kù)獲取數(shù)據(jù),返回HttpServlet,HttpServlet將數(shù)據(jù)轉(zhuǎn)發(fā)給JSP,JSP負(fù)責(zé)將數(shù)據(jù)渲染為HTML,由Tomcat負(fù)責(zé)將HTML轉(zhuǎn)化為HTTP響應(yīng),返回客戶端。

4. --> 通過(guò)互聯(lián)網(wǎng),通過(guò)HTTP協(xié)議 -->

5. 客戶端瀏覽器接收到HTTP響應(yīng),瀏覽器將HTML渲染為頁(yè)面,并運(yùn)行其中可能存在的JavaScript進(jìn)一步調(diào)整界面。


整個(gè)流程必須由開(kāi)發(fā)者精確設(shè)計(jì)才能運(yùn)作流暢,其中客戶端HTML和JavaScript屬于前端設(shè)計(jì),服務(wù)器運(yùn)行的其他內(nèi)容屬于后端設(shè)計(jì)。雖然符合J2EE規(guī)范的Tomcat等應(yīng)用服務(wù)器已經(jīng)幫我們實(shí)現(xiàn)了最復(fù)雜的一塊,即HTTP協(xié)議部分,還給我們提供了JSP這個(gè)模板引擎,以及自定義標(biāo)簽等手段。但是在控制層,在模型層,J2EE能給我們的幫助少之甚少。


就拿用戶提交一個(gè)表單為例,而我們?cè)赟ervlet中獲取參數(shù)為例,雖然不用我們解析HTTP報(bào)文,應(yīng)該已經(jīng)是要謝天謝地了,但是我們要做的事情仍然很多,分析一下:


1. 客戶端傳過(guò)來(lái)的數(shù)據(jù)全是文本,而我們需要的是Java對(duì)象。

2. 凡是文本就有編碼問(wèn)題,而這需要前后端配合解決。

3. 客戶端的輸入是不可信的,我們必須校驗(yàn)參數(shù)的合法性。

4. 我們還必須將校驗(yàn)結(jié)果反饋給客戶,并且最好不要讓客戶全部重新輸入。

5. 我們往往不是只有一個(gè)參數(shù)需要,而是有幾個(gè)甚至更多參數(shù),要妥善的處理各種情況組合。


這些事情幾乎全部都需要我們手動(dòng)編碼來(lái)完成,幾乎每一個(gè) Servlet 都充斥著這樣的代碼,設(shè)置編碼,獲取參數(shù),校驗(yàn)參數(shù),校驗(yàn)通不過(guò)返回錯(cuò)誤信息,校驗(yàn)通過(guò)則進(jìn)行業(yè)務(wù)處理。而更重要的是,獲取參數(shù)僅僅是整個(gè)流程中的一小步,我們的Servlet中存在著大量的重復(fù)性,機(jī)械性代碼,而處理業(yè)務(wù)邏輯的代碼可能只有一兩行。



JavaWeb框架

既然存在著大量的重復(fù),我們當(dāng)然不能忍,必須請(qǐng)出DRY大法。顯然JavaWeb應(yīng)用是一個(gè)規(guī)模龐大,流程復(fù)雜的應(yīng)用,我們正需要JavaWeb框架的幫助。以Struts2框架為例,他能給我們什么幫助呢?


1. 在控制層,由Struts2的核心控制器接管控制權(quán),將本來(lái)在Web.xml進(jìn)行配置的一些工作,轉(zhuǎn)移到自定義的struts.xml文件中,這個(gè)文件的配置形式更友好。

2. Struts2封裝了Serlvet Api,使用POJO對(duì)象作為控制器(Action),大量使用反射,不要求繼承特定類,有利于復(fù)用及單元測(cè)試。提供ActionSupport類,結(jié)合struts2標(biāo)簽,能很方面實(shí)現(xiàn)的校驗(yàn)信息的收集及反饋。

3. 提供國(guó)際化支持,在顯示層有國(guó)際化相關(guān)的標(biāo)簽,在控制層由國(guó)際化相關(guān)的API。提供基于配置的校驗(yàn)及JS生成技術(shù)。智能化的參數(shù)類型轉(zhuǎn)換,支持自定義轉(zhuǎn)換器。提供Action攔截器,方便實(shí)現(xiàn)AOP模式。

4. 提供了基于OGNL表達(dá)式的數(shù)據(jù)共享模式,前后端數(shù)據(jù)交流更簡(jiǎn)單,提供了Struts2標(biāo)簽庫(kù),簡(jiǎn)單好用,支持多種模板,如FreeMarker,支持各種插件,如JSON,支持整合多種框架,如Spring??傊痪湓?,能在各方各面給我們強(qiáng)大的幫助。



所以當(dāng)然要學(xué)框架,要用框架,那么要怎么學(xué)?

1. 用框架要知其然,還要知其所以然,要大體明白框架實(shí)現(xiàn)一個(gè)功能特性的原理,不能只是會(huì)用,只是覺(jué)得很神奇就可以了。就拿前面的Hibernate + Spring聲明式事務(wù)為例,要弄明白框架這部分是怎么實(shí)現(xiàn)的。

2. 首先要夯實(shí)你的語(yǔ)言基礎(chǔ),如JavaSE基礎(chǔ),語(yǔ)法掌握,用法掌握,有些同學(xué)語(yǔ)法還不熟練就開(kāi)始學(xué)框架,等于地基沒(méi)打就起高樓,你可能會(huì)快一步,但是遲早要遇到瓶頸,甚至摔跟頭。

3. 那么何時(shí)開(kāi)始學(xué)習(xí)框架?我不建議新手一開(kāi)始就直接使用框架。

就好像一開(kāi)始學(xué)習(xí)編程語(yǔ)言,大家都不推薦直接使用IDE,一定要用命令行自己編譯運(yùn)行幾個(gè)文件之后,了解清楚了之后才可以使用IDE,要不然對(duì)于底層原理不了解,遇到問(wèn)題沒(méi)法自己手動(dòng)排查。

4. 使用框架也是一樣,如果不是自己寫多了重復(fù)性的代碼,就很難理解框架為什么要這么設(shè)計(jì)。如果不嘗試幾種不同的實(shí)現(xiàn),就很難理解框架為了靈活性而做出的設(shè)計(jì)和擴(kuò)展點(diǎn)。如果不寫幾十個(gè)權(quán)限檢查語(yǔ)句,就很難理解AOP到底有什么好處。

5. 框架這么好,我該全部使用框架嗎?首先只有在規(guī)模以上的程序中,才有應(yīng)用框架的必要,一個(gè)簡(jiǎn)單的程序沒(méi)必要使用框架,當(dāng)然如果你很熟練,使用也無(wú)所謂。

6. 要學(xué)習(xí)一下框架的核心源代碼,要為擴(kuò)展框架做好準(zhǔn)備,因?yàn)殡m然框架基本上還算靈活,但是面對(duì)錯(cuò)綜復(fù)雜的業(yè)務(wù)需求,永遠(yuǎn)不可能面面俱到,而你不了解框架的話,可能會(huì)給你實(shí)現(xiàn)業(yè)務(wù)需求造成麻煩。這也是有些人堅(jiān)持使用Servlet+JSP原生開(kāi)發(fā),而不是用框架的理由。

7. 只要程序大了,歸根究底還是要使用框架的,不是用別人寫好的,就是自己寫一套。這里我不建議自己寫,不要重復(fù)造輪子,總有專業(yè)造輪子的。你草草寫就的往往不如別人已經(jīng)千錘百煉的代碼。除非你是為了學(xué)習(xí)與研究的目的,自己寫,那就是一件很好的事情。


Release Notes

Popular Entries