玩轉SpringBoot—SpringBoot簡介和基本用法
學習目標
- 微服務架構的演進——推導單體架構到微服務架構一路走來的根本原因。
- 深層次理解spring的問題。
- 理解spring一路走來所做的努力。
- springboot對spring的優(yōu)化。
- springboot使用。
第1章:微服務架構的演進
1、單體架構
任何一個網站在發(fā)布初期幾乎都不可能立馬就擁有龐大的用戶流量和海量數(shù)據(jù),都是在不停地試錯過程中一步一步演變其自身架構,滿足其自身業(yè)務。比如現(xiàn)在能夠抗住雙十一這么大流量的淘寶,它的技術最早用的是 LAMP(Linux+Apache+Mysql+Php)。
實際上,架構越復雜,意味著業(yè)務的體量越龐大。
對于一個剛剛起步的項目,我們會選擇最簡單最快速的方式來實現(xiàn)。而單體架構是最好的選擇,目前很多的傳統(tǒng)軟件行業(yè)仍然采用這類的架構。
一般的實施方案是,把所有的功能模塊都打包在一個(jar、war),并且部署在一個 web 容器下,比如 tomcat、weblogic、jboss 中運行
2、集群架構
一旦用戶量以及流量開始增加,服務器的性能就會遇到瓶頸,這個時候必須要對系統(tǒng)架構做調整以及優(yōu)化。而在這個階段主要需要解決的問題是提升業(yè)務系統(tǒng)的并行處理能力,降低單機系統(tǒng)負載,以便支撐更多的用戶訪問操作。
集群就是一種很好的方式,它可以把多臺獨立的服務器通過網絡連接進行組合,對外形成一個整體提供服務。當一臺服務器的處理能力接近或已超出其容量上限時,我們不會去嘗試換一個更高性能的服務器,因為投入產出比不高,一般的做法就是采用集群技術,通過增加新的服務器來分散并發(fā)訪問流量,只要業(yè)務系統(tǒng)能夠隨意支持服務器的橫向擴容,那么從理論上來說就應該無懼任何挑戰(zhàn),從而實現(xiàn)可伸縮性和高可用性架構。
3、業(yè)務垂直化拆分
雖然通過集群可以提升并行處理能力以及對于高可用的實現(xiàn),但是同時還需要考慮到業(yè)務的復雜度,如果仍然把所有的業(yè)務邏輯全部耦合在一起放在一個 war 包中來管理,那對于代碼的維護和擴展來說是非常困難的。而且如果某個業(yè)務功能出現(xiàn)故障,會導致整個系統(tǒng)不可用。所以這個階段要做的就是降低業(yè)務的耦合度,提升系統(tǒng)的容錯性。
所以這個時候可以對業(yè)務進行垂直化拆分,簡單來說,就是可以按照系統(tǒng)的業(yè)務功能拆分出多個業(yè)務模塊,比如電商網站,會拆分出:首頁、用戶、搜索、訂單、支付、商品等子系統(tǒng)。每個子系統(tǒng)由不同的業(yè)務團隊負責。
4、服務化改造
隨著對業(yè)務系統(tǒng)進行垂直化改造之后,以業(yè)務功能緯度拆分出來多個子系統(tǒng),而在各個子系統(tǒng)中,會存在比較多的共享業(yè)務,比如用戶信息查詢,在支付業(yè)務中會涉及到、在首頁中也會涉及到。那么勢必會造成重復開發(fā)產生非常多的冗余代碼。那么這個時候就引入了服務化改造的思想,也就是 SOA把一些通用的、會被多個上層服務調用的模塊獨立拆分出來,形成一些共享的基礎服務。這些被拆分出來的共享服務相對來說是比較獨立,并且可重用。 比如用戶管理服務,包含用戶注冊、用戶查詢等功能。比如單點登錄服務;
SOA 的核心目標就是通過服務的流程化來實現(xiàn)業(yè)務的靈活性,而這個流程化其實就是由一系列相關聯(lián)的任務組成,這一系列相關聯(lián)的任務可以通過一系列的服務組合來實現(xiàn)具體的業(yè)務功能SOA 面向服務架構,從語義上說,它與面向過程、面向對象、面向組件一樣,是一種軟件組建及開發(fā)的方式。所以在 SOA 中,服務是最核心的抽象手段,業(yè)務被劃分為一些列粗粒度的業(yè)務服務和業(yè)務流程
SOA 中更強調 ESB 企業(yè)服務總線,企業(yè)服務總線可以使得服務之間的交互是動態(tài)的,以及服務位置是透明的。這樣的好處是服務的調用者和服務的提供者之間是高度解耦的。從而使得服務有更高的靈活性以及隔離性。
ESB: 是從面相服務架構(SOA)發(fā)展過來的,主要是對多個系統(tǒng)中的服務調用者和服務提供者的解耦。ESB 本身提供了服務暴露、接入、協(xié)議轉化、數(shù)據(jù)格式轉化、路由等功能。
SOA 主要解決的問題是:
- 信息孤島
- 互聯(lián)互通
- 業(yè)務重用
5、微服務架構
業(yè)務系統(tǒng)實施服務化改造后,原本共享的業(yè)務被拆分,形成可復用的服務,可以在最大程度上避免共享業(yè)務的重復建設、資源連接瓶頸等問題出現(xiàn)。那么那些被拆分出來的服務,是否也需要以業(yè)務功能為維度來進行拆分,使之能夠獨立進行部署,以降低業(yè)務藕合和提升容錯性呢?
微服務并不是一種新思想的方法。它更像是一種思想的精煉,是一種服務化思想的最佳實踐方向而已,所以我認為微服務其實是在 SOA 思路下,隨著各個企業(yè)對于服務化治理上不斷地完善,以及對軟件的交付鏈路以及基礎設施逐步成熟之下的一種自然的產物。 微服務也是一種面向服務的架構模型,只是它更強調服務的粒度。也就是服務的職責更加單一更加精煉我們也可以把 SOA 看成是微服務的超集。 也就是說多個微服務可以組成一個 soa 服務。
6、微服務和 SOA 架構的區(qū)別
經常會有同學問,微服務和 SOA 架構有什么區(qū)別。這個區(qū)別一定要從架構的發(fā)展過程來了解。這兩種架構模式,其實本質上應該是在分布式架構這條時間線上,基于服務化思想的不斷完善,以及基礎設施的逐步成熟之下的一種升級。既然存在于時間線的先后,那也就意味著,這兩種架構模式所關注的點不一樣
- SOA 關注的是服務的重用性、以及解決企業(yè)內部的信息孤島問題。
- 微服務關注的是解耦,解耦和可重用性在特定的角度來看是一樣,但本質上是不同的。解耦是降低業(yè)務之間的耦合度(也就是微服務關注的服務粒度),而可重用性關注的是服務的復用。
- 微服務會使用更輕量級的通信協(xié)議,使用 Restful 風格的 API。輕量級協(xié)議可以很好地支持跨語言,使得語言生態(tài)更加豐富。
- 微服務會更多地關注 Devops 持續(xù)交付,因為服務粒度更細使得開發(fā)運維變得更加重要。所以微服務與容器化技術的結合更加緊密。
- SOA 應該是微服務的超集。
隨著架構的不斷演進,底層框架為了滿足需求也在不斷地努力,spring為了簡化開發(fā),從最開始xml配置到后面的注解配置,其實都在簡化開發(fā)這條路上不斷努力,但是spring依然做的不夠,而且也無法滿足微服務架構的各種組件引入帶來的各種配置,這個時候springboot產生了,那么接下來,我們先來看看spring做出了哪些努力,又有什么不足之處。
第2章:Spring的演進
spring的核心思想實際上就是IoC、DI、AOP三大塊,它的核心目的就是為了簡化開發(fā),容器化管理我們的bean對象。基于這個目的,spring做了很多努力,在一定程度上,spring確實簡化了開發(fā),但是隨著業(yè)務復雜度越來越深,功能需求越來越大,各種組件的出現(xiàn),spring的使用也開始變的吃力,這個吃力實際上就體現(xiàn)在兩個方便:bean對象注入到IoC容器的過程越來越麻煩;配置文件越來越多,無法統(tǒng)一管理。事實上,spring也做過很多的努力,我們現(xiàn)在看看它的發(fā)展史吧。
先創(chuàng)建spring的maven項目,然后通過集成springMVC和Mybatis舉例
項目創(chuàng)建
添加依賴包
<?xml versinotallow="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-vip-jt-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>spring-vip-jt-demo Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!--spring 版本號-->
<spring.version>5.2.8.RELEASE</spring.version>
<!--mybatis 版本號-->
<mybatis.version>3.5.6</mybatis.version>
</properties>
<dependencies>
<!--spring 核心包-->
<!-- spring start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring end -->
<!--mybatis核心包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.8.0-alpha0</version>
<scope>test</scope>
</dependency>
<!--j2ee相關包 servlet、jsp、jstl-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--mybatis/spring 包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!--MySQL 驅動包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
</project>
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Archetype Created Web Application</display-name>
<!--welcome pages-->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 解決post亂碼解決在url中傳遞中文參數(shù)時的亂碼 -->
<filter>
<filter-name>CharacterEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 配置所有請求都經過該攔截器,即所有資源都統(tǒng)一使用 utf-8 防止亂碼 -->
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置springmvc DispatcherServlet-->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--配置dispatcher.xml作為mvc的配置文件-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<!--
1、load-on-startup元素標記容器是否在啟動的時候就加載這個servlet(實例化并調用其init()方法);
2、當值為0或者大于0時,表示容器在應用啟動時就加載并初始化這個servlet;
3、當值小于0或者沒有指定時,則表示容器在該servlet被選擇時才會去加載;
4、正數(shù)的值越小,該servlet的優(yōu)先級越高,應用啟動時就越先加載;
5、當值相同時,容器就會自己選擇順序來加載。
-->
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<!-- /* 可以匹配所有的請求-->
<!-- 會匹配到所有像 /login 這樣的路徑型url,但不會匹配到 后綴型的url(即 *.html等) -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--把applicationContext.xml加入到配置文件中-->
<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>
</web-app>
配置springMCV.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--此文件負責整個mvc中的配置-->
<!-- 自動掃描裝配 -->
<context:component-scan base-package="com.example"/>
<!--啟用spring的一些annotation -->
<context:annotation-config/>
<!-- 配置注解驅動 可以將request參數(shù)與綁定到controller參數(shù)上 -->
<mvc:annotation-driven/>
<!--靜態(tài)資源映射-->
<!--本項目把靜態(tài)資源放在了webapp的statics目錄下,資源映射如下-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/image/**" location="/images/"/>
<mvc:default-servlet-handler /> <!--這句要加上,要不然可能會訪問不到靜態(tài)資源,具體作用自行百度-->
<!-- 對模型視圖名稱的解析,即在模型視圖名稱添加前后綴(如果最后一個還是表示文件夾,則最后的斜杠不要漏了) 使用JSP-->
<!-- 默認的視圖解析器 在上邊的解析錯誤時使用 (默認使用html)- -->
<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/><!--設置JSP文件的目錄位置-->
<property name="suffix" value=".jsp"/>
<property name="exposeContextBeansAsAttributes" value="true"/>
</bean>
</beans>
配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- demo02包通過注解自動掃描 -->
<context:component-scan base-package="com.example.demo02"/>
</beans>
創(chuàng)建a.jsp
<html>
<body>
<h2>${version}</h2>
<h2>${name}:${msg}</h2>
</body>
</html>
(1)Spring1.x時代
在此時因為jdk1.5剛剛出來,注解開發(fā)并未盛行,因此一切Spring配置都是xml格式,想象一下所有的bean都用xml配置,細思極恐啊,心疼那個時候的程序員2秒
在applicationContext.xml中配置
<!-- demo01包通過xml配置 -->
<bean id="helloService01" class="com.example.demo01.HelloService01"/>
controller
package com.example.demo01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Eclipse_2019
* @create 2021/7/31 17:52
*/
@Controller
public class HelloController01 {
@Autowired
private HelloService01 helloService01;
@RequestMapping("/hello01")
public ModelAndView hello01(@RequestParam String name){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("version","1.X版本");
modelAndView.addObject("name",name);
modelAndView.addObject("msg",helloService01.sayHello(name));
modelAndView.setViewName("a");
return modelAndView;
}
}
service
public class HelloService01 {
public String sayHello(String name){
return "你真棒!"+name;
}
}
測試
public class DemoMain {
public static void main(String[] args) {
// ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
System.out.println(context.getBean(HelloService01.class));
}
}
Tomcat啟動。
(2)Spring2.x時代
Spring引入了注解開發(fā),但是因為并不完善,因此并未完全替代xml,此時的程序員往往是把xml與注解進行結合,貌似我們之前都是這種方式。
- @Required/@Repository/@Aspect
spring 2.5
- @Component
- @Service
- @Controller
- @RequestMapping
在applicationContext.xml增加配置
<context:component-scan base-package="com.example.demo02"/>
controller
@Controller
public class HelloController02 {
@Autowired
private HelloService02 helloService02;
@RequestMapping("/hello02")
public ModelAndView hello(@RequestParam String name){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("version","2.X版本");
modelAndView.addObject("name",name);
modelAndView.addObject("msg",helloService02.sayHello(name));
modelAndView.setViewName("a");
return modelAndView;
}
}
service
@Service
public class HelloService02 {
public String sayHello(String name){
return "你好帥啊!";
}
}
測試
public class Demo02Main {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
System.out.println(context.getBean(HelloController02.class));
}
}
Tomcat啟動。
3、Spring3.x時代
(1)Configuration
3.0以后Spring的注解已經非常完善了,因此Spring推薦大家使用完全的java配置來代替以前的xml,不過似乎在國內并未推廣盛行。然后當SpringBoot來臨,人們才慢慢認識到java配置的優(yōu)雅。
- @Configuration 去XML化
configuration
package com.example.demo03;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Eclipse_2019
* @create 2021/8/3 17:16
*/
@Configuration
public class SpringConfiguration {
@Bean
public HelloService03 helloService03(){
return new HelloService03();
}
@Bean
public HelloController03 helloController03(){
return new HelloController03();
}
}
controller同2.x版本
service
public class HelloService03 {
public String sayHello(String name){
return "你好帥?。?;
}
}
測試同上。
(2)Import
案例見spring-vip-jt-demo的demo04中//
(3)Enable
案例見spring-vip-jt-demo的demo05中。
- @Enable模塊驅動
(3)Spring4.x時代
- @Conditional
案例見spring-vip-jt-demo的demo06中
springboot條件注解
@ConditionalOnBean(僅僅在當前上下文中存在某個對象時,才會實例化一個Bean)。
@ConditionalOnClass(某個class位于類路徑上,才會實例化一個Bean)。
@ConditionalOnExpression(當表達式為true的時候,才會實例化一個Bean)。
@ConditionalOnMissingBean(僅僅在當前上下文中不存在某個對象時,才會實例化一個Bean)。
@ConditionalOnMissingClass(某個class類路徑上不存在的時候,才會實例化一個Bean)。
@ConditionalOnNotWebApplication(不是web應用)。
5、集成Mybatis
集成Redis或者mybatis要怎么做:
1.導包
2.創(chuàng)建配置文件
mybatis配置舉例:
配置spring-mybatis.xml
<?xml versinotallow="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--1 引入屬性文件,在配置中占位使用 -->
<context:property-placeholder location="classpath*:db.properties" />
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--配置數(shù)據(jù)庫信息-->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--聲明MyBatis中提供的SqlSessionFactoryBean,用于創(chuàng)建SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--引用注入,將數(shù)據(jù)庫連接池賦值給dataSource-->
<property name="dataSource" ref="dataSource"/>
<!--MyBatis主配置文件位置,configLocation為Resource類型,讀取配置文件-->
<property name="configLocation" value="classpath:mybatis.xml"></property>
<!--用于指定mapper.xml文件的位置
如果Mapper.xml與Dao接口文件在同一個包下且同名,spring中MapperScannerConfigurer掃描Dao接口文件的同時會自動掃描同名的Mapper.xml并裝配到Dao接口文件
如果Mapper.xml與Dao接口文件不在同一個包下或者不同名,就必須使用配置mapperLocations指定mapper.xml的位置
此時spring是通過識別mapper.xml中的<mapper namespace=""> namespace的值來確定對應的Mapper.class-->
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
</bean>
<!--創(chuàng)建Dao對象,使用SqlSession的getMapper(dao.class)
MapperScannerConfigurer:在內部調用getMapper()生成每個Dao接口的代理對象-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定sqlSessionFactory的ID-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--指定包名,包名為Dao接口所在包名,MapperScannerConfigurer掃描該包,為每個接口執(zhí)行getMapper()方法,
得到每個接口的Dao對象,創(chuàng)建好的Dao對象放入Spring容器-->
<property name="basePackage" value="com.example.demo07"/>
</bean>
</beans>
配置mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- settings -->
<settings>
<!-- 打開延遲加載的開關 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 將積極加載改為消極加載(即按需加載) -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 打開全局緩存開關(二級緩存)默認值就是 true -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 別名定義 -->
<typeAliases>
<package name="com.example.demo07"/>
</typeAliases>
<!-- 加載映射文件 -->
<mappers>
<mapper class="com.example.demo07.UserDao"/>
</mappers>
</configuration>
通過上面這種方式才能把mybatis注入到我們springIOC容器中,但是這種方式太麻煩了。怎么做更簡便呢?
第3章:SpringBoot應運而生
1、簡介
(1)是什么
Springboot是Spring項目中的一個子工程,與我們所熟知的Spring-framework 同屬于spring的產品:
官網地址
:https://spring.io/projectsactuator:https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints
我們可以看到下面的一段介紹:
Takes an opinionated view of building production-ready Spring applications. Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible.
翻譯一下:
用一些固定的方式來構建生產級別的spring應用。Spring Boot 推崇約定大于配置的方式以便于你能夠盡可能快速的啟動并運行程序。
其實人們把Spring Boot 稱為搭建程序的腳手架。其最主要作用就是幫我們快速的構建龐大的spring項目,并且盡可能的減少一切xml配置,做到開箱即用,迅速上手,讓我們關注與業(yè)務而非配置。
(2)為什么
java一直被人詬病的一點就是臃腫、麻煩。當我們還在辛苦的搭建項目時,可能Python程序員已經把功能寫好了。為了解決這些問題,然后出現(xiàn)了一個框架叫做Spring,Spring翻譯過來就是春天,意味著程序員的春天來了,但是真的是這樣嗎?其實大佬們創(chuàng)建出Spring這個框架本質上就是為了給程序員們減負,為了使我們構建項目更加便捷,為了讓我們開發(fā)更加快速,但是呢,早期的Spring框架還是會有很多問題,最主要的兩點就是:
- 復雜的配置
項目各種配置其實是開發(fā)時的損耗, 因為在思考 Spring 特性配置和解決業(yè)務問題之間需要進行思維切換,所以寫配置擠占了寫應用程序邏輯的時間。
- 一個是混亂的依賴管理
項目的依賴管理也是件吃力不討好的事情。決定項目里要用哪些庫就已經夠讓人頭痛的了,你還要知道這些庫的哪個版本和其他庫不會有沖突,這難題實在太棘手。并且,依賴管理也是一種損耗,添加依賴不是寫應用程序代碼。一旦選錯了依賴的版本,隨之而來的不兼容問題毫無疑問會是生產力殺手。
而SpringBoot讓這一切成為過去!
Spring Boot 簡化了基于Spring的應用開發(fā),只需要“run”就能創(chuàng)建一個獨立的、生產級別的Spring應用。Spring Boot為Spring平臺及第三方庫提供開箱即用的設置(提供默認設置,存放默認配置的包就是啟動器),這樣我們就可以簡單的開始。多數(shù)Spring Boot應用只需要很少的Spring配置。
我們可以使用SpringBoot創(chuàng)建java應用,并使用java –jar 啟動它,就能得到一個生產級別的web工程。
(3)特性
Spring Boot 主要目標是:
- 為所有 Spring 的開發(fā)者提供一個非??焖俚?、廣泛接受的入門體驗
- 開箱即用(啟動器starter-其實就是SpringBoot提供的一個jar包),但通過自己設置參數(shù)(.properties),即可快速擺脫這種方式。
- 提供了一些大型項目中常見的非功能性特性,如內嵌服務器、安全、指標,健康檢測、外部化配置等
- 絕對沒有代碼生成,也無需 XML 配置。
自動配置、Starter組件、Actuator、命令行界面(CLI) 是 Spring Boot 最重要的 4 大核心特性,其中 CLI 是 Spring Boot 的可選特性,雖然它功能強大,但也引入了一套不太常規(guī)的開發(fā)模型,因而這里僅關注其它 3 種特性。
2、快速入門
接下來,我們就來利用Springboot快速搭建一個web工程
(1)創(chuàng)建工程
(2)編寫controller
代碼:
@RestController
public class HelloController {
@GetMapping("hello")
public String hello(){
return "hello, spring boot!";
}
}
(3)啟動項目
接下來,我們運行main函數(shù),查看控制臺:
- 監(jiān)聽的端口是8080
打開頁面訪問:http://localhost:8080/hello
3、集成mybatis
引包
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
配置文件
spring.datasource.username=root
spring.datasource.password=jingtian
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.8.74:3306/test
server.port=8080
mybatis.mapper-locations=classpath:*Mapper.xml
controller
package com.example.springbootvipjtdemo.demo01.controller;
import com.example.springbootvipjtdemo.demo01.dao.entity.User;
import com.example.springbootvipjtdemo.demo01.services.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Eclipse_2019
* @create 2021/8/2 16:33
*/
@RestController
public class HelloController {
@Autowired
IUserService userService;
@PostMapping("addUser")
public String addUser(@RequestBody User user){
int a = userService.insert(user);
if(a!=0){
return "插入成功";
}else{
return "失敗";
}
}
}
service
package com.example.springbootvipjtdemo.demo01.services;
import com.example.springbootvipjtdemo.demo01.dao.entity.User;
public interface IUserService {
int insert(User user);
}
package com.example.springbootvipjtdemo.demo01.services.impl;
import com.example.springbootvipjtdemo.demo01.dao.entity.User;
import com.example.springbootvipjtdemo.demo01.dao.mappers.UserMapper;
import com.example.springbootvipjtdemo.demo01.services.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author Eclipse_2019
* @create 2021/8/2 16:47
*/
@Service
public class UserServiceImpl implements IUserService {
@Autowired
UserMapper userMapper;
@Override
public int insert(User user) {
return userMapper.insert(user);
}
}
dao
package com.example.springbootvipjtdemo.demo01.dao.mappers;
import com.example.springbootvipjtdemo.demo01.dao.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper {
int insert(User user);
}
mapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootvipjtdemo.demo01.dao.mappers.UserMapper">
<resultMap id="BaseResultMap" type="com.example.springbootvipjtdemo.demo01.dao.entity.User">
<id column="userid" property="userID"/>
<result column="username" property="userName"/>
</resultMap>
<insert id="insert" parameterType="com.example.springbootvipjtdemo.demo01.dao.entity.User" keyProperty="userId" useGeneratedKeys="true">
insert into user(username,age) values(#{userName,jdbcType=VARCHAR},#{age,jdbcType=BIGINT})
</insert>
</mapper>
啟動類
package com.example.springbootvipjtdemo.demo01;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.example.springbootvipjtdemo.demo01.dao.mappers")
@SpringBootApplication(scanBasePackages = {"com.example.springbootvipjtdemo.demo01"})
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}