1. 程式人生 > >碼不停蹄(六):從零開始Java後臺開發,跳出寫Servlet+JDBC的坑,使用輕量級框架Spring+SpringMVC+MyBatis (SSM)

碼不停蹄(六):從零開始Java後臺開發,跳出寫Servlet+JDBC的坑,使用輕量級框架Spring+SpringMVC+MyBatis (SSM)

寫在前面:這篇文章是寫給剛剛接觸或者準備學習web/APP應用開發的同學的,分享我的後臺開發經驗,如果你對後臺開發沒有什麼概念,甚至剛剛學完Java的基礎語法,那麼請一定要仔細看我接下來提供的開發方案,這會幫你跳出很多坑,迅速找到入門後臺開發的路。

一、學點底層的東西,不用框架開發後臺

雖然博主說要“跳出寫Servlet+JDBC的坑”,但是還是要簡單介紹一下這個坑,沒有入過這個坑的朋友很難對框架開發的帶來的便捷有所體會。

  • 你也許曾經Google/百度過“如何編寫在伺服器上執行的程式”、“怎樣搭建一個伺服器”這些關鍵詞句,那麼一定會有所瞭解servlet、tomcat。

  • 你肯定也百度過“後臺怎麼操縱資料庫”這類問題,那麼JDBC你一定不會陌生。

  • 一個不使用框架的後臺,靠上面這些關鍵詞就能搭建出來。

(1)Servlet:簡單來說就是Java的一個類,它可以響應http請求,只要將它部署到伺服器上,在一個叫web.xml的檔案裡新增一個對映關係(將某個URL指向這個類.class)就能通過特定的URL來訪問,比如配置“/servlet_1”這個URL字尾指向servlet_1.class,就能通過http://localhost:8080/servlet_1呼叫servlet_1.class,也就是說客戶端只要向這個URL傳送報文,伺服器就會自動呼叫對應的servlet來處理請求報文。
介紹一個學習servlet書寫的教程:菜鳥教程–Servlet


(2)Tomcat:一個開源的輕量級伺服器,小專案或者測試用這個最方便不過了,只要Tomcat處於啟動狀態,搭載著它的主機(你的電腦)就是一臺能被外界通過IP訪問的伺服器。
(3)JDBC:這就不用介紹太多了,連線資料庫用的。

  • 優點:是不是覺得很簡單,我只要在電腦/伺服器上安裝tomcat,拷貝整個專案到tomcat安裝目錄下的webapp資料夾,然後重啟tomcat,就能通過URL呼叫程式中的servlet了,servlet可以處理請求。

  • 缺點:簡單代表著什麼事都要你做:

(1)大家瞭解一下JDBC怎麼增、刪、查、改,就會發現它實在太繁瑣了,比如你有一個User類,儲存使用者資訊,當你想要插入一個user時,你也許會像下面這樣寫。但你會疑惑,如果user的name為null怎麼辦,要知道JDBC的空值不是這樣插入的。這時你就不得不分情況討論,使用if判斷,不同情況對應不同的sql語句。即使提供佔位符機制的 PreparedStatement 類也有諸如此類的問題,需要提前判斷各個欄位的取值。這還只是插入操作,想想一般的表十幾個欄位很正常,多的幾十個、上百個欄位,這種寫法,想想都頭皮發麻。兩個字,“繁瑣”。

// 使用 Statement 構建查詢語句
String sql = "insert into user(name, password, age) values ('" + user.getName() 
   + "','" + user.getPassword + "'," +user.getAge() + ")" ;
// 使用 PreparedStatement 構建查詢語句
String sql = "insert into user(name, password, age) values (?,?,?)";
...
preparedStatement.setString(1, user.getName());
preparedStatement.setString(2, user.getPassword());
preparedStatement.setInt(3, user.getAge());

(2)servlet的配置問題,一個servlet對應一個類,一個http報文,基本格式如下,每寫一個servlet就要寫這麼多東西,之後還要修改web.xml。三個字,“很繁瑣”。

public class Servlet_1 extends HttpServlet{
  public void init() throws ServletException{
      // 初始化
  }
  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      // 處理Get類請求
  }
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      // 處理Post類請求
  }
  public void destroy() {
      // 銷燬servlet
  }
}
  • 如果你還在使用這種方式,或者正在做這方面的準備,趕緊停下來,寫了一個月servlet的博主如此說道。可能有人會疑惑為什麼我不直接講解框架的使用,而是介紹servlet?其實道理很簡單,所有的框架都是對底層的一些封裝,我們剛剛接觸開發,有一些坑不得不踩,只有瞭解了這些坑,才會明白我們怎麼走才是正確的。

二、基於SSM框架的後臺開發

如果你是一個Java工程師,那麼肯定對Spring有所耳聞,Java EE 的開發離不開Spring,學習Spring要關注IOC、AOP的概念,以後再開貼介紹,大家先自行百度。當然還有更加簡便的Spring boot框架(一個基於Spring的強大框架,也是微服務的基礎,建議學會使用SSM後馬上投入Spring boot 的學習)。限於篇幅,我不可能面面俱到地講解SSM框架的各種應用,但我會對它的特色進行介紹。就像我一向推崇的,我不會過多地介紹技術點,我會給你開發的思路,告訴你怎樣跳過那些坑,儘可能地減少你盲目百度的時間(可以理解為我告訴你該百度什麼,挺有意思的)。

  • 接下來,跟著我碼程式碼吧!!!文章結束會給GitHub的demo,不過是基於intellij idea 的,eclipse的童鞋就自己將src資料夾、pom.xml拷貝到eclipse中吧。

1、新增依賴(具體看demo的pom.xml檔案)
不會使用maven工程的童鞋自行百度這是個什麼東西,說白了就是不用自己手動下載jar包再匯入工程。直接新增一個 dependencypom.xml檔案就能自動從中央倉庫下載jar包,是不是很方便。更大的作用就是一個專案的所有成員不用將jar包傳來傳去,大家新增一樣的依賴就能統一jar包版本。
2、配置檔案:這是Spring的一個特色,使用配置檔案的方式取代程式碼控制,比如資料庫的連線。
(1)applicationContext.xml——這是Spring的配置檔案。資料來源(dataSource)就是你的資料庫,幾個屬性都比較好理解,驅動是mysql的(需要新增mysql-connector的依賴),url就是資料庫地址,使用者名稱,密碼。事務管理器就是管理事務的(事務的概念不用我介紹了吧)。至於標籤<bean>,代表這個類交給容器來管理,用到它的時候會從容器獲取,而不是自己new一個物件出來,也就是常說的依賴注入(DI)。

...
    <!-- 配置資料來源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://{your_ip}:{your_port}/{your_database_name}?characterEncoding=UTF-8"/>
        <property name="username" value="..."/>
        <property name="password" value="..."/>
    </bean>

    <!-- 配置事務管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 開啟事務註解驅動,這樣就能通過註釋來使用事務 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <!-- 配置mybatis工廠,使用mybatis框架執行資料的增刪查改 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 開啟包註解掃描指定的包,這樣容器就能通過註釋例項化bean物件 -->
    <context:component-scan base-package="org.XuJiaLe"/>

    <!-- 開啟Mapper掃描指定的包,mapper就是增刪查改的sql語句 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.XuJiaLe.mapper"/>
    </bean>
...

(2)springmvc-config.xml——SpringMVC的配置檔案。只有兩個父標籤,主要是第二個標籤,有時候我們向後臺請求的不是一個頁面,而是一些資料,為了能直接將物件以json格式返回,我們會結合@ResposneBody來使用,請繼續往下看。

    <!-- 開啟包掃掃描 -->
    <context:component-scan base-package="com.example.controller"/>

    <!-- mvc註解驅動 -->
    <mvc:annotation-driven>
        <!-- 配置轉換器,便於將POJO物件直接以json格式返回前端,不需要可以刪除,只保留父標籤 -->
        <mvc:message-converters>
            <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <!-- 轉換為json -->
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

3、註解:Spring的又一大特色,使用註解來簡化xml的編寫,上面的配置檔案算是很簡化了,因為我接下來介紹的都是基於註解的,這樣就免除大家寫配置檔案的痛苦。也推薦大家使用註解而不是xml檔案的方式來開發。當然,使用註解要開啟註解掃描,這樣才能對包裡的註解進行編譯,細心的朋友應該留意到我在配置檔案中說的開啟包掃描吧。
4、邏輯處理
(1)在org.xujiale.entity包下寫個實體類User。

package com.example.entity;

public class User {
    private long id;  //資料庫設計的時候就設為自增型別的,便於管理
    private String name;
    private String account;
    private int age;
    // 省略了一堆getter和setter,大家懂得啦
}

(2)再寫個mapper,提供對資料庫的插入和查詢(一般會以介面的形式提供給上一層呼叫)。解釋一下程式碼,@ Repository註釋和@bean類似,一般是傳統資料訪問層(Dao)的例項化。而@Insert、@Select等就是mybatis的註解,可以直接將sql語句放入註解中,是不是很方便,類似還有@Delete、@Update。

package com.example.mapper;

@Repository
public interface UserMapper {
    // 插入資訊
    @Insert("insert into user(name,password,age) values(#{name},#{password},#{age})")
    int insert(User user);
    
    //查詢資訊
    @Select("select * from user where name=#{name}")
    User select(@Param("name") String name);
}

(3)有了底層資料訪問,還要提供服務層(Service),寫個UserService介面用來提供給上一層呼叫,還是提供兩個方法。

package com.example.service

public interface UserService {
    // 新增使用者
    int addUser(User user);
    // 獲取使用者資訊
    User getUser(long id);
}

服務層就不能像資料訪問層一樣只提供介面了,服務層有時涉及很多業務邏輯,我們寫一個UserService介面的實現類UserServiceImpl來處理一些邏輯,但是我們的demo比較簡單,所以直接返回資料訪問的資料或者結果。@Service和@Repository類似,不過特指服務層的例項;@Transactional就是事務,只要新增一下注釋就能將方法加入事務中,十分方便;@Autowired代表自動裝配,容器會自動向新增該註解的變數注入例項,所以我們可以直接使用mapper,無須new,當然,前提是我們之前為mapper添加了@Repository註解。

package con.example.service
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper mapper;  //呼叫下一層mapper介面
    @Override
    public int addUser(User user) {
        return mapper.insert(user);
    }
    @Override
    public User getUser(long id) {
        return mapper.select(id);
    }
}

(4)接下來就是controller層了。@Controller和@Service等類似,特指controller層的例項。@RequestMapping就是指定我們URL的對映路徑;@RequestParam用於提取http報文中的引數;留意@ResponseBody,在新增這個註釋之後,配合我們上面在springmvc-config.xml中的配置就能實現將User這個POJO類物件以json格式返回。同時,使用這個註釋也代表這個方法的返回值不需要經過檢視解析器(這個是什麼大家百度一下吧,是用來做頁面跳轉的),直接返回給前端。

package com.example.controller

@Controller
public class UserController {

    @Autowired
    UserService userService;  //呼叫service介面

    @RequestMapping(value = "/AddUser")
    @ResponseBody
    public String addUser(@RequestParam("name") String name,
                          @RequestParam("password") String password,
                          @RequestParam("age")int age) {
        User user = new User();
        user.setName(name);
        user.setPassword(password);
        user.setAge(age);

        int result = userService.addUser(user);  //獲取結果
        if (result == 1) {  //受影響行數為1,說明資料庫已經插入,所以返回成功("Succeed")
            return "Succeed";
        }
        return "Failed";
    }

    @RequestMapping(value = "/GetUser")
    @ResponseBody
    public User getUser(@RequestParam("id") long id) {
        return userService.getUser(id);  //直接向前端返回這個物件
    }
}

5、最後配置web.xml檔案,完整檔案看demo吧,注意我將applicationContext.xml和springmvc-config.xml放在類路徑,也就是和com資料夾同級的位置。

    ...
    <!-- 配置載入Spring檔案的監聽器,載入spring配置檔案 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    ...
    <!-- 配置Spring MVC 前端核心控制器,用這個來實現URL對映 -->
    <servlet>
        <servlet-name>crm</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 載入springmvc的配置檔案 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>
        <!-- 伺服器啟動立即載入配置檔案 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 所有請求都需要通過控制器 -->
    <servlet-mapping>
        <servlet-name>crm</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    ...

6、最後一步就是將專案打包成war包,放到伺服器的webapp目錄下 ,重啟之後就能直接通過URL發出請求。
(1)發起一個“新增使用者”請求,拼接一個get請求,ip:埠(預設8080)/工程名/contrller某個方法的對映路徑?引數。post就用表單提交吧。
測試1
結果,返回了Succeed,也就是說明插入成功了。
測試2

(2)發起一個檢視使用者的請求。可以看到id為1(也就是我們剛剛插入的使用者)的資料已經返回來了,而且就是json格式。
測試3

至此關於SSM框架的基本應用已經講得差不多了,當然講解的只是冰山一角,希望這個小demo會對你的學習有所幫助,能夠給你找到一條學習後臺開發的路。最後給出GitHub地址
ssm-demo

博文如有不當之處歡迎指正,也歡迎大家來我的主頁檢視其他博文,共同進步。