1. 程式人生 > 實用技巧 >Java Springboot學習(三) 整合springmvc、jdbc、mybatis

Java Springboot學習(三) 整合springmvc、jdbc、mybatis

1.整合SpringMVC

剛才案例已經能實現mvc自動配置,這裡我們主要解決以下3個問題

  • 修改埠
  • 靜態資源
  • 攔截器配置

修改埠


檢視SpringBoot的全域性屬性可知,埠通過以下方式配置:

# 對映埠
server.port=80

重啟服務後測試:

訪問靜態資源


ResourceProperties的類,裡面就定義了靜態資源的預設查詢路徑:

預設的靜態資源路徑為:

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public

只要靜態資源放在這些目錄中任何一個,SpringMVC都會幫我們處理。

我們習慣會把靜態資源放在 classpath:/static/ 目錄下。我們建立目錄,並且新增一些靜態資源:

重啟專案後測試:

新增攔截器


攔截器也是我們經常需要使用的,在SpringBoot中該如何配置呢?

首先我們定義一個攔截器:

public class LoginInterceptor implements HandlerInterceptor {
    
    private Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
    
    @Override
    public
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { logger.debug("處理器執行前執行!"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { logger.debug(
"處理器執行後執行!"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { logger.debug("跳轉後執行!"); } }

通過實現 WebMvcConfigurer 並新增 @Configuration 註解來實現自定義部分SpringMvc配置:

@Configuration
public class MvcConfig implements WebMvcConfigurer{
    /**
    * 通過@Bean註解,將我們定義的攔截器註冊到Spring容器
    * @return
    */
    @Bean
    public LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }

    /**
    * 重寫介面中的addInterceptors方法,新增自定義攔截器
    * @param registry
    */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 通過registry來註冊攔截器,通過addPathPatterns來新增攔截路徑
        registry.addInterceptor(this.loginInterceptor()).addPathPatterns("/**");
    }
}

ant path路徑匹配萬用字元

  • ‘?’ 匹配任何單字元
  • ‘*’ 匹配0或者任意數量的字元
  • ‘/**’ 匹配0或者更多的目錄

結構如下:

接下來執行並檢視日誌:

你會發現日誌中什麼都沒有,因為我們記錄的log級別是debug,預設是顯示info以上,我們需要進行配置。

SpringBoot通過 logging.level.*=debug 來配置日誌級別,*填寫包名

# 設定com.lxs包的日誌級別為debug
logging.level.com.lxs=debug

再次執行檢視:

2018-05-05 17:50:01.811 DEBUG 4548 --- [p-nio-80-exec-1] com.lxs.interceptor.LoginInterceptor
: preHandle method is now running!
2018-05-05 17:50:01.854 DEBUG 4548 --- [p-nio-80-exec-1] com.lxs.interceptor.LoginInterceptor
: postHandle method is now running!
2018-05-05 17:50:01.854 DEBUG 4548 --- [p-nio-80-exec-1] com.lxs.interceptor.LoginInterceptor
: afterCompletion method is now running!

2.整合jdbc

匯入t_user.sql資料庫指令碼

/*
SQLyog Ultimate v12.09 (64 bit)
MySQL - 5.7.18 : Database - springboot
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`springboot` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `springboot`;

/*Table structure for table `tb_user` */

DROP TABLE IF EXISTS `tb_user`;

CREATE TABLE `tb_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(50) DEFAULT NULL,
  `password` varchar(50) DEFAULT NULL,
  `name` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `sex` int(11) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  `created` date DEFAULT NULL,
  `updated` date DEFAULT NULL,
  `note` varchar(2000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Data for the table `tb_user` */

insert  into `tb_user`(`id`,`user_name`,`password`,`name`,`age`,`sex`,`birthday`,`created`,`updated`,`note`) values (1,'zhangsan','1','張三',18,1,'2019-02-27','2019-02-27','2019-02-27','在學習Java...'),(2,'lisi','1','李四',18,1,'2019-02-27','2019-02-27','2019-02-27','在學習Java...'),(3,'wangwu','1','王五',18,1,'2019-02-27','2019-02-27','2019-02-27','在學習Java...'),(4,'fanbingbing','1','范冰冰',18,2,'2019-02-27','2019-02-27','2019-02-27','在學習Java...'),(5,'guodegang','1','郭德綱',18,1,'2019-02-27','2019-02-27','2019-02-27','在學習Java...');

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

當然,不要忘了資料庫驅動,SpringBoot並不知道我們用的什麼資料庫,這裡我們選擇MySQL:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.46</version>
</dependency>

配置連線池

其實,在剛才引入jdbc啟動器的時候,SpringBoot已經自動幫我們引入了一個連線池:

HikariCP應該是目前速度最快的連線池了,我們看看它與c3p0的對比:

因此,我們只需要指定連線池引數即可:

# 連線四大引數
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=123
# 可省略,SpringBoot自動推斷
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.minimum-idle=10

實體類

public class User implements Serializable {
    private Long id;
    // 使用者名稱
    //自動轉換下換線到駝峰命名user_name -> userName
    private String userName;
    // 密碼
    private String password;
    // 姓名
    private String name;
    // 年齡
    private Integer age;
    // 性別,1男性,2女性
    private Integer sex;
    // 出生日期
    private Date birthday;
    // 建立時間
    private Date created;
    // 更新時間
    private Date updated;
    // 備註
    private String note;
}

dao

@Repository
public class JdbcDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public List<User> findAll() {
        return jdbcTemplate.query("select * from tb_user", new BeanPropertyRowMapper<>(User.class));
    }
}

測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class JdbcDaoTest {

    @Autowired
    private JdbcDao jdbcDao;

    @Test
    public void findAll() {
        List<User> list = jdbcDao.findAll();
        for (User user : list) {
        System.out.println(user);
        }
    }
}

3.整合mybatis


mybatis


SpringBoot官方並沒有提供Mybatis的啟動器,不過Mybatis官網自己實現了:

<!--mybatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>

配置,基本沒有需要配置的:

# mybatis 別名掃描
mybatis.type-aliases-package=com.lxs.domain
# mapper.xml檔案位置,如果沒有對映檔案,請註釋掉
mybatis.mapper-locations=classpath:mappers/*.xml

實體類,直接使用之前jdbc用到的實體類

public class User implements Serializable {
    private Long id;
    // 使用者名稱
    //自動轉換下換線到駝峰命名user_name -> userName
    private String userName;
    // 密碼
    private String password;
    // 姓名
    private String name;
    // 年齡
    private Integer age;
    // 性別,1男性,2女性
    private Integer sex;
    // 出生日期
    private Date birthday;
    // 建立時間
    private Date created;
    // 更新時間
    private Date updated;
    // 備註
    private String note;
}

介面

public interface UserDao {
    public List<User> findAll();
}

對映檔案

<?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.lxs.demo.dao.UserDao">   <select id="findAll" resultType="user">     select * from tb_user   </select> </mapper>

Mapper的載入介面代理物件方式有2種

第一種:使用@Mapper註解(不推薦)

需要注意,這裡沒有配置mapper介面掃描包,因此我們需要給每一個Mapper介面新增 @Mapper 註解,才能被識別。

第二種設定MapperScan,註解掃描的包(推薦)

@MapperScan("dao所在的包"),自動搜尋包中的介面,產生dao的代理物件

@SpringBootApplication
@MapperScan("com.lxs.demo.dao")
    public class Application {
        public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

測試

引入測試構建

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

測試程式碼

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {
    @Autowired
    private UserDao userDao;
    @Test
    public void testFindAll() {
        List<User> list = userDao.findAll();
    }
}

通用mapper


概念

使用Mybatis時,最大的問題是,要寫大量的重複SQL語句在xml檔案中,除了特殊的業務邏輯SQL語句之外,

還有大量結構類似的增刪改查SQL。而且,當資料庫表結構改動時,對應的所有SQL以及實體類都需要更改。

這大量增加了程式設計師的負擔。避免重複書寫CRUD對映的框架有兩個:

  • 通用mybatis(tk mybatis)
  • mybatis plus,通能更加強大

通用Mapper的作者也為自己的外掛編寫了啟動器,我們直接引入即可:

<!-- 通用mapper -->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.0.2</version>
</dependency>

實體類

tk mybatis 實體類使用的註解是jpa註解

@Table(name = "tb_user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 使用者名稱
    private String userName;
    ....

注意事項:

1. 預設表名=類名,欄位名=屬性名

2. 表名可以使用 @Table(name = "tableName") 進行指定

3. @Column(name = "fieldName") 指定

4. 使用 @Transient 註解表示跟欄位不進行對映

不需要做任何配置就可以使用了。

@Mapper
public interface UserMapper extends tk.mybatis.mapper.common.Mapper<User>{
    public List<User> findByUser(User user);
}

自定義對映檔案

映射覆雜方法 resources/mappers/UserMapper.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.lxs.demo.dao.UserMapper">
    <select id="findByUser" resultType="user">
    SELECT * FROM tb_user
    <where>
        <if test="name != null">
        name like '%${name}%'
        </if>
        <if test="note != null">
        and note like '%${note}%'
        </if>
    </where>
    </select>
</mapper>

一旦繼承了Mapper,繼承的Mapper就擁有了Mapper所有的通用方法:

  

Select 方法: List<T> select(T record); 說明:根據實體中的屬性值進行查詢,查詢條件使用等號
方法: T selectByPrimaryKey(Object key); 說明:根據主鍵欄位進行查詢,方法引數必須包含完整的主鍵屬性,
查詢條件使用等號
方法: List<T> selectAll(); 說明:查詢全部結果,select(null)方法能達到同樣的效果
方法: T selectOne(T record); 說明:根據實體中的屬性進行查詢,只能有一個返回值,有多個結果是丟擲異
常,查詢條件使用等號
方法: int selectCount(T record); 說明:根據實體中的屬性查詢總數,查詢條件使用等號
Insert 方法: int insert(T record); 說明:儲存一個實體,null的屬性也會儲存,不會使用資料庫預設值
方法: int insertSelective(T record); 說明:儲存一個實體,null的屬性不會儲存,會使用資料庫預設值
Update 方法: int updateByPrimaryKey(T record); 說明:根據主鍵更新實體全部欄位,null值會被更新
方法: int updateByPrimaryKeySelective(T record); 說明:根據主鍵更新屬性不為null的值
Delete 方法: int delete(T record); 說明:根據實體屬性作為條件進行刪除,查詢條件使用等號
方法: int deleteByPrimaryKey(Object key); 說明:根據主鍵欄位進行刪除,方法引數必須包含完整的主鍵屬性
Example方法 方法: List<T> selectByExample(Object example); 說明:根據Example條件進行查詢 重點:這
個查詢支援通過 Example 類指定查詢列,通過 selectProperties 方法指定查詢列
方法: int selectCountByExample(Object example); 說明:根據Example條件進行查詢總數
方法: int updateByExample(@Param("record") T record, @Param("example") Object example); 說明:根據
Example條件更新實體 record 包含的全部屬性,null值會被更新
方法: int updateByExampleSelective(@Param("record") T record, @Param("example") Object example); 說
明:根據Example條件更新實體 record 包含的不是null的屬性值
方法: int deleteByExample(Object example); 說明:根據Example條件刪除資料

注意要把MapperScan類改成tk-mybatis構件的類

import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@EnableConfigurationProperties
@MapperScan("com.lxs.demo.dao")
    public class Application {

注意:必須使用tk mybatis的MapperScan

啟動測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {
    @Autowired
    private UserDao userDao;

    @Test
    public void testFindByUser() {
        User condition = new User();
        condition.setName("a");
        List<User> list = userMapper.findByUser(condition);
        for (User user : list) {
            System.out.println(user);
        }
}

@Test
public void testFindAll() {
    List<User> list = userDao.selectAll();
    for (User user : list) {
        System.out.println(user);
    }
}

@Test
public void testFindById() {
    User user = userDao.selectByPrimaryKey(4);
    System.out.println(user);
}

@Test
public void testFindByExample() {
    Example example = new Example(User.class);
    example.createCriteria().andLike("name", "%a%");
    userMapper.selectByExample(example).forEach(user -> {
    System.out.println(user);
    });
}

@Test
public void testInsert() {
    User user = new User();
    user.setAge(18);
    user.setBirthday(new Date());
    user.setCreated(new Date());
    user.setName("周星馳");
    userDao.insert(user);
}