Spring Boot+Mybatis專案總結

席潤發表於2019-02-13

IDEA建立maven專案

使用IDEA建立maven專案,勾選從模板原型構建,這裡選擇maven-archetype-quickstart型別,這種型別的maven專案以jar包的方式提供對外統一的輸出,這是最快速的一個構建Spring Boot研發專案的模板。在沒有Spring Boot的開發框架時,更多的選擇maven-archetype-webapp,這種方式建立的是以war包方式部署在Tomcat或JBoss這種J2EE的容器。詳見Maven官方文件

建立成功後,需要給目錄指定其為什麼目錄,選定專案資料夾,右鍵選擇Mark Directory as,然後選擇目錄型別。還要在main目錄下建立resources目錄並指定型別。main目錄下的java目錄下放置java原始碼,resources目錄下放置spring、spring boot等的資源配置檔案。

從零整合專案

進入Spring官方文件,檢視Build with Maven目錄下pom.xml檔案,從其中複製spring-boot-starter-parent依賴到專案中的pom.xml檔案中,這樣當前的專案就是Spring Boot專案。並在專案pom檔案標籤內引入spring-boot-starter-parent下的spring-boot-starter-web和spring-boot-starter-test專案。

在APP class上加@EnableAutoConfiguration註解 將APP的啟動類當成可以支援自動化配置的bean,並且能夠開啟整個工程類基於springboot的自動化的配置,然後用下面這行程式碼啟動Spring Boot。

SpringApplication.run(App.class,args);
複製程式碼

要實現Spring MVC的***controller***功能,則引入註解@RestController或@Controller

Spring Boot 對應的配置化操作,只需要在resources目錄下建立預設配置檔案——application.yml或application.properties,在其中進行配置。

整合Mybatis

進入pom檔案,確定使用的資料庫,使用mysql,則引入mysql-connector-java包;確定使用什麼連線池來管理mysql的連結,這裡使用阿里巴巴的druid連線池。然後將spring boot對mybatis的支援引入,這裡使用mybatis-spring-boot-starter包;在配置檔案類匯入mybatis需要的一些配置,用來啟動一個帶mybatis資料庫訪問的一個spring boot工程,例:

mybatis:
  mapper-locations: classpath:mapping/*.xml

spring:
  datasource:
    name: miaohsa
    url: jdbc:mysql://localhost:3306/miaosha?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    username: root
    password: 123456
    #使用druid資料來源
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
複製程式碼
mybatis的自動生成工具

然後使用mybatis的自動生成工具,用來生成對應資料庫檔案的對映。

在pom中引入mybatis自動生成的外掛,例:

<plugin>
  <groupId>org.mybatis.generator</groupId>
  <artifactId>mybatis-generator-maven-plugin</artifactId>
  <version>1.3.5</version>
  <dependencies>
    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>1.3.5</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
  </dependencies>
  <executions>
    <execution>
      <id>mybatis generator</id>
      <phase>package</phase>
      <goals>
        <goal>generate</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <!--允許移動生成的檔案-->
    <verbose>true</verbose>
    <!--不允許自動覆蓋檔案-->
    <overwrite>false</overwrite>
    <configurationFile>
      src/main/resources/mybatis-generator.xml
    </configurationFile>
  </configuration>
</plugin>
複製程式碼

其中mybatis-generator.xml檔案在官網中有,可貼上過來,刪改使用,例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

    <context id="DB2Tables" targetRuntime="MyBatis3">
        <!--資料庫連結地址賬號密碼-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/miaosha?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=UTC"
                        userId="root"
                        password="123456">
        </jdbcConnection>

        <!--生成dataobject類的存放位置-->
        <javaModelGenerator targetPackage="com.miaosha.dataobject" targetProject="src/main/java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--生成對映檔案存放位置-->
        <sqlMapGenerator targetPackage="mapping"  targetProject="src/main/resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!--生成Dao類的存放位置-->
        <!-- 客戶端程式碼,生成易於使用的針對Model物件和XML配置檔案的程式碼
              type="ANNOTATIONDMAPPER",生成Java Model和基於註解的Mapper 物件
              type="MIXEDMAPPER",生成基於註解的Java Model和相應的Mapper物件
              type="XMLMAPPER",生成SQLMap XML 檔案和獨立的Mapper介面
         -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.miaosha.dao"  targetProject="src/main/java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <!--生成對應表和類名-->
        <table tableName="user_info" domainObjectName="UserDO" enableCountByExample="false"
               enableUpdateByExample="false" enableSelectByExample="false"
               enableDeleteByExample="false" selectByExampleQueryId="false"></table>
        <table tableName="user_password" domainObjectName="UserPasswordDO" enableCountByExample="false"
               enableUpdateByExample="false" enableSelectByExample="false"
               enableDeleteByExample="false" selectByExampleQueryId="false"></table>

    </context>
</generatorConfiguration>
複製程式碼

在Run/Debug Configuration下新建一個Maven的配置,例:

mybatis generator

將@EnableAutoConfiguration註解改為@SpringBootApplication,其等價於以預設屬性使用@Configuration , @EnableAutoConfiguration 和@ComponentScan 。最終啟動類註解例:

@SpringBootApplication(scanBasePackages = {"com.miaosha"})
@RestController
@MapperScan("com.miaosha.dao")
複製程式碼

SpringMVC方式進行開發

使用SpringMVC方式進行開發,專案結構

專案結構

其中dao層dataobject層由mybatis自動生成工具生成,dataobject層(負責資料儲存到service層的傳輸)下的類對應資料庫物件模型,其中的欄位與資料庫一一對映,dao層下的類定義對資料庫進行互動的方法,在resources的mapping目錄下有自動生成dao層對應的配置檔案,一起實現對資料庫的操作。

service層下model目錄下建立物件模型(不可以把資料庫的對映簡單透傳返回給想要service的服務,這個model對應Spring MVC中業務邏輯互動的模型),然後在資料庫中建立對應的表,在service層下建立對應物件的service介面,介面中定義需要的方法(方法的返回型別大部分為model物件),在service層下impl目錄下去實現。新增方法:在mapping目錄下對應配置檔案中新增相應的SQL語句,在dao目錄下的對應介面中建立對映(新增方法)。

:若資料庫表中設有自增id,需在mapping目錄下配置檔案中的insert標籤中新增屬性useGeneratedKeys="true" 和keyProperty="id",指定自增id

在serviceImpl中定義資料庫物件dataobject與模型物件model相互轉換的方法,在controller中定義模型物件model與檢視物件viewobject相互轉換的方法,這裡使用到了org.springframework.beans.BeanUtils方法(作用為將一個Bean物件中的資料封裝到另一個屬性結構相似的Bean物件中,有些屬性可能由於型別原因無法封裝,需要手動新增)。

serviceImpl類與controller類中分別需要新增**@Service註解和@Controller註解**

response層定義了統一返回型別,有一個通用物件,最終返回前端的物件為該通用物件

error層有一個common error介面,一個Enum列舉類實現該介面,該列舉類通過構造方法構造一個實現common error介面的enum型別的子類,一個繼承Exception且實現common error方法的類,其內強關聯一個對應的common error(即enum類),且實現其對應建構函式以方便使用。該方式對應設計模式——包裝器業務異常類實現

controller層下viewobject目錄下建立可供UI使用的物件,其中的欄位為可以給使用者檢視的欄位。在controller層下建立對應物件的controller類,在其中呼叫其service介面中的方法來實現相應邏輯。

controller層下還有一個基類BaseController,其定義了controller類下介面上的@RequestMapping註解中的屬性consumes(指定處理請求的提交內容型別)的預設值(GET請求不需要);並通過定義exceptionhandler解決未被controller層吸收的exception(為業務邏輯處理上的問題或業務邏輯錯誤而並非服務端不能處理的錯誤),例:

@ExceptionHandler(Exception.class)//需要指明收到什麼樣的exception之後才會進入它的處理環節,此處定義為根類
@ResponseStatus(HttpStatus.OK)//捕獲到controller丟擲的exception,並返回HttpStatus.OK,即status=200
@ResponseBody //handler exception使用這種方式(Object會尋找本地頁面檔案)僅僅只能返回頁面路徑,無法處理viewobject類對應的@ResponseBody形式,加上@ResponseBody註解即可解決
public Object handlerException(HttpServletRequest request, Exception ex){
    //獲取異常並處理
}
複製程式碼

其他所有controller類都要繼承基類BaseController

在UserController中,使用者登入介面中將登陸憑證加入到使用者登入成功的session

@Autowired
private HttpServletRequest httpServletRequest;
//通過bean的方式注入進來,代表這個HttpServletRequest是單例模式
//單例模式怎麼可以支援一個request支援多個使用者的併發訪問?
//bean包裝的HttpServletRequest,本質是一個proxy,它內部擁有ThreadLocal方式的map,去讓使用者在每個執行緒當中去處理它自己對應的request,
//並且有ThreadLocal清除機制,可以放心使用,且這個HttpServletRequest對應當前使用者的http請求
複製程式碼
//將登陸憑證加入到使用者登入成功的session中,分散式中用token
this.httpServletRequest.getSession().setAttribute("IS_LOGIN",true);
this.httpServletRequest.getSession().setAttribute("LOGIN_USER",userVO);
複製程式碼
登入密碼加密

因為jdk自帶的MD5實現的方式只支援16位MD5,更改加密方法,例:

//將密碼加密
public String EncodeByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    //確定計算方法
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    BASE64Encoder base64Encoder = new BASE64Encoder();
    //加密字串
    String newstr = base64Encoder.encode(md5.digest(str.getBytes("utf-8")));
    return newstr;
}
複製程式碼

validator層下為格式化校驗規則,在pom檔案中引入Apache Commons Lang包,使用了其StringUtils工具類;還引入了hibernate-validator包來進行校驗。其下建立一個校驗結果物件,物件中還建立一個獲取錯誤資訊的方法以便使用;並建立一個實現InitializingBean類的一個校驗實現類,將hibernate validator 通過工廠校驗的方式使其例項化,然後實現校驗方法並返回校驗結果物件。另外對欄位有什麼限制可在model層下物件模型的欄位上新增註解如@NotBlank、@NotNull、@Max、@Min等。

跨域解決

在controller類上加上如下註解:

@CrossOrigin(allowCredentials = "true",allowedHeaders = "*")  //實現跨域
複製程式碼

DEFAULT_ALLOW_CREDENTIALS = true:

需配合前端設定xhrFields授信後, 使得跨域session共享

前端ajax請求新增設定:xhrFields:{withCredentials:true}

DEFAULT_ALLOWED_HEADERS = *:

允許跨域傳輸所有的header引數,將用於使用token放入header域做session共享的跨域請求

參考

慕課課程《SpringBoot構建電商基礎秒殺專案》,推薦,老師講得特別好

程式碼地址