Spring Boot原理分析之簡單示例

本文使用spring和mybatis整合爲例,分別使用兩種配置,一種是xml文件和屬性文件配置項目,一種是spring boot自動配置項目的方式,兩種方式進行對比,從項目配置上看看差別。

項目文件

不管是xml配置項目,還是自動配置,和業務相關的文件,是不變的。

表結構

CREATE TABLE `t_auth_user` (
  `id` bigint(16) NOT NULL AUTO_INCREMENT,
  `user_account` varchar(64) NOT NULL COMMENT '賬號',
  `password` varchar(255) NOT NULL COMMENT '密碼',
  `is_delete` tinyint(1) DEFAULT '0' COMMENT '刪除標識0:未刪除,1:已刪除',
  `nickname` varchar(64) DEFAULT NULL COMMENT '暱稱',
  `remark` varchar(64) DEFAULT NULL COMMENT '備註',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mapper xml

mybatis映射文件spring-boot-source-read/src/main/resources/mappers/AuthUserMapper.xml

<?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.spboot.read.mapper.AuthUserMapper">
    <resultMap id="BaseResultMap" type="com.spboot.read.beans.AuthUser">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="user_account" property="userAccount" jdbcType="VARCHAR"/>
        <result column="password" property="password" jdbcType="VARCHAR"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
        <result column="is_delete" property="isDelete" jdbcType="TINYINT"/>
    </resultMap>
    <sql id="Base_Column_List">
        id, user_account, password, create_time, update_time, is_delete
    </sql>
    <select id="query" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from t_auth_user
        where user_account = #{userAccount}
    </select>
</mapper>

AuthUserMapper.java

接口AuthUserMapper.java

package com.spboot.read.mapper;

import com.spboot.read.beans.AuthUser;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface AuthUserMapper {
    List<AuthUser> query(String userAccount);
}

AuthUser

實體類AuthUser.java

package com.spboot.read.beans;

import java.util.Date;
public class AuthUser {
    private Long id;
    private String userAccount;
    private String password;
    private Date createTime;
    private Date updateTime;
    private Byte isDelete;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUserAccount() {
        return userAccount;
    }
    public void setUserAccount(String userAccount) {
        this.userAccount = userAccount == null ? null : userAccount.trim();
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password == null ? null : password.trim();
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public Byte getIsDelete() {
        return isDelete;
    }
    public void setIsDelete(Byte isDelete) {
        this.isDelete = isDelete;
    }
}

服務類

package com.spboot.read.service;

import com.spboot.read.beans.AuthUser;
import java.util.List;
public interface IAuthUserService {
	List<AuthUser> query(String userAccount);
}

package com.spboot.read.service.impl;

import com.spboot.read.beans.AuthUser;
import com.spboot.read.mapper.AuthUserMapper;
import com.spboot.read.service.IAuthUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.*;
@Service
public class AuthUserServiceImpl implements IAuthUserService {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Resource
	private AuthUserMapper authUserMapper;
	public AuthUserServiceImpl(){
		logger.info("創建 com.test.bean.AuthUserServiceImpl");
	}
	@Override
	public List<AuthUser> query(String userAccount) {
		if(StringUtils.isEmpty(userAccount)){
			return null;
		}
		return authUserMapper.query(userAccount);
	}
}

Spring+XML配置

先看看項目的整體目錄結構
在這裏插入圖片描述

pom文件

<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.sp.source.read</groupId>
	<artifactId>spring-souce-read</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.2.0.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.8.6</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.6</version>
		</dependency>
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.9.2</version>
			<exclusions>
				<exclusion>
					<artifactId>commons-logging</artifactId>
					<groupId>commons-logging</groupId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>1.10</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>3.2.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.2.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.27</version>
		</dependency>
		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.2.5</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.38</version>
		</dependency>
		<!-- mybatis-spring 整合 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.2.2</version>
		</dependency>
		<!-- Spring Jdbc 的支持 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.2.0.RELEASE</version>
		</dependency>
		<!-- logger -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>2.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.5</version>
		</dependency>
		<!-- 格式化對象,方便輸出日誌 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.16</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

屬性配置

application.properties,存放在resources目錄下

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=utf8&amp;allowMultiQueries=true
jdbc.username=****
jdbc.password=****
jdbc.validationQuery=SELECT 1

bean配置

spring-config.xml,存放在resources目錄下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 加載配置文件 -->
    <context:property-placeholder location="classpath:application.properties"/>
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    <context:component-scan base-package="com.sp.source.read"/>
    <bean id="dbCommProperty" abstract="true">
        <!-- 初始化連接大小 -->
        <property name="initialSize" value="5"/>
        <!-- 連接池最大使用連接數量 -->
        <property name="maxActive" value="5"/>
        <!-- 連接池最小空閒 -->
        <property name="minIdle" value="5"/>
        <!-- 獲取連接最大等待時間 -->
        <property name="maxWait" value="60000"/>
        <property name="validationQuery" value="${jdbc.validationQuery}"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>
        <property name="testWhileIdle" value="true"/>
        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000"/>
        <!-- 打開removeAbandoned功能 -->
        <property name="removeAbandoned" value="true"/>
        <!-- 1800秒,也就是30分鐘 -->
        <property name="removeAbandonedTimeout" value="1800"/>
        <!-- 關閉abanded連接時輸出錯誤日誌 -->
        <property name="logAbandoned" value="true"/>
    </bean>
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
          destroy-method="close" parent="dbCommProperty">
        <property name="url"
                  value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>
    <!-- 配置 SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 加載數據源 -->
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath*:mappers/*Mapper.xml"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定掃描的包,如果存在多個包使用(逗號,)分割 -->
        <property name="basePackage" value="com.sp.source.read"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    <!-- 配置事物管理器 TransactionManager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:advice id="interceptorAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="Exception"/>
            <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
            <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
            <tx:method name="query*" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>
    <!-- 配置切面 aop -->
    <aop:config>
        <aop:pointcut id="transactionPointcut" expression="execution(* com.test.service.*.*(..))"/>
        <aop:advisor pointcut-ref="transactionPointcut" advice-ref="interceptorAdvice"/>
    </aop:config>
</beans>

日誌配置

log4j.xml,存放在resources目錄下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
    <!-- 控制檯的日誌記錄 -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%p][%d{yyyy-MM-dd HH\:mm\:ss}][%c][%m]%n" />
        </layout>
    </appender>
    <root>
        <priority value="debug" />
        <appender-ref ref="console" />
    </root>
</log4j:configuration>

測試類

創建一個測試類,測試spring和mybatis整合

package com.sp.source.read.service;

import com.alibaba.fastjson.JSON;
import com.sp.source.read.bean.AuthUser;
import com.sp.source.read.service.impl.AuthUserServiceImpl;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AuthUserServiceImplTest {
    private static Logger logger = Logger.getLogger(AuthUserServiceImplTest.class);
    
    public static void main(String[] args){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
        IAuthUserService authUserServiceImpl = ctx.getBean(AuthUserServiceImpl.class);
        Map<String,Object> params = new HashMap<>();
        params.put("userAccount","user002");
        AuthUser authUser = new AuthUser();
        authUser.setUserAccount("user002");
        authUser.setId((long) 4);
        List<AuthUser> authUserList = authUserServiceImpl.query(params);
        logger.info("執行結果:"+ JSON.toJSONString(authUserList));
    }
}

執行結果:

[INFO][2020-07-07 20:26:33][AuthUserServiceImplTest][執行結果:[
{
    "createTime":1548162759000,
    "id":4,
    "isDelete":0,
    "password":"dd9b254be95d548383d9616307f9c73f",
    "updateTime":1556876038000,
    "userAccount":"user002"
}
]]

Spring Boot自動配置

先看看項目的整體目錄結構
在這裏插入圖片描述

pom文件

<?xml version="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>spring-boot-source-read</groupId>
    <artifactId>com.spboot.read</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Spring Boot 源碼研讀項目</name>
    <description>Spring Boot 源碼研究</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
    </parent>

    <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>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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>
            <version>5.1.38</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

屬性配置

application.yml,放到resources目錄下

spring:
  profiles:
    active: dev

application-dev.yml,放到resources目錄下

server:
  port: 8080

spring:
  datasource:
    username: ****
    password: ****
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
    driver-class-name: com.mysql.jdbc.Driver

mybatis:
  mapper-locations: classpath:mappers/*Mapper.xml
  type-aliases-package: com.spboot.read.beans

#日誌
logging:
  config: classpath:logback-spring.xml
  level:
    root: info

日誌配置

logback-spring.xml,放到resources目錄下

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
    <contextName>logback</contextName>
    <!--輸出到控制檯-->
    <appender name="stdoutAppender" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <pattern>[%p][%d{yyyy-MM-dd HH:mm:ss}][%c %L][%m]%n</pattern>
        </encoder>
    </appender>
    <root>
        <appender-ref ref="stdoutAppender" />
    </root>
</configuration>

項目入口類

package com.spboot.read;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 項目啓動入口
 */
@MapperScan("com.spboot.read.mapper")
@SpringBootApplication
public class SpBootReadApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpBootReadApplication.class, args);
    }
}

Controller

控制類,提供一個http地址,查詢數據庫表中記錄

package com.spboot.read.controller;
import com.spboot.read.beans.AuthUser;
import com.spboot.read.service.IAuthUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/authUser/")
public class UserController {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);
    @Resource
    private IAuthUserService authUserService;
    @RequestMapping("query/{userAccount}")
    public List<AuthUser> query(@PathVariable String userAccount) {
        logger.info("請求參數userAccount:{}", userAccount);
        Assert.notNull(userAccount, "賬號不能爲空");
        List<AuthUser> userList = authUserService.query(userAccount);
        return userList;
    }
}

IDEA啓動配置

創建一個spring boot項目啓動配置,Main class選擇項目的入口類
在這裏插入圖片描述
瀏覽器訪問地址:

http://localhost:8080/authUser/query/user002

返回結果:

[
    {
        "id":4,
        "userAccount":"user002",
        "password":"dd9b254be95d548383d9616307f9c73f",
        "createTime":"2019-01-22T13:12:39.000+00:00",
        "updateTime":"2019-05-03T09:33:58.000+00:00",
        "isDelete":0
    }]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章