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 publicboolean 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); }