主要知識點
SpringBoot2集成MyBatis,實現基本的CURD操作,這其中涉及到相關內容也是關注重點:
- PageHelper 數據庫分頁查詢,重點配置和使用
- Durid 數據庫連接池集成,主要爲sql監控而生。重點配置和使用
- MyBatis 集成及使用
- Controller controller層接收參數
SpringBoot整合Mybatis
之前已經說過:SpringBoot框架不是對Spring功能上的增強,而是提供了一種快速使用Spring的方式
所以說,SpringBoot整合Mybatis的思想和Spring整合Mybatis的思想基本相同,不同之處有兩點:
- Mapper接口的XML配置文件變化。之前我們使用Mybatis接口代理開發,規定Mapper映射文件要和接口在一個目錄下;而這裏Mapper映射文件置於resources/mapper/下,且置於src/main/java/下的Mapper接口需要用@Mapper註解標識,不然映射文件與接口無法匹配。
- SpringBoot建議使用YAML作爲配置文件,它有更簡便的配置方式。所以整合Mybatis在配置文件上有一定的區別,但最終都是那幾個參數的配置。
整合配置文件
在Spring階段用XML配置mybatis無非就是配置:1.連接池;2.數據庫url連接;3.mysql驅動;4.其他初始化配置
SpringBoot 推薦yml格式配置文件,配置更加簡潔,當然.properties格式也是支持的,對於其它配置一樣,都在yml配置文件中,配置最大程度簡單話,儘量摒棄之前SpringMVC中的xml配置
server:
port: 8081
spring:
datasource:
name: local_mysql_a50
# url: jdbc:mysql://127.0.0.1:3306/supports-demo2?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
url: jdbc:mysql://localhost:3306/ssm_a50_db?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
username: root
password: WFCwfc123456!@#
# 使用druid數據源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
filters: stat,wall #通過別名的方式配置擴展插件,常用的插件有:監控統計用的filter:stat,日誌用的filter:log4j,防禦sql注入的filter:wall
minIdle: 10 #最小空閒連接個數
maxActive: 100 #最大連接個數
initialSize: 10 #初始化連接個數
maxWait: 60000 #獲取連接時最大等待時間,單位毫秒
timeBetweenEvictionRunsMillis: 60000 #配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒ååå
minEvictableIdleTimeMillis: 300000 #配置一個連接在池中最小生存的時間,單位是毫秒
validationQuery: select 'x' #用來檢測連接是否有效的sql,要求是一個查詢語句。
testWhileIdle: true #建議配置爲true,不影響性能,並且保證安全性。如果空閒時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效
testOnBorrow: false #申請連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能
testOnReturn: false #歸還連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能
poolPreparedStatements: true #是否緩存preparedStatement,也就是PSCache。PSCache對支持遊標的數據庫性能提升巨大,比如說oracle。在mysql下建議關閉。
maxPoolPreparedStatementPerConnectionSize: 100 #要啓用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改爲true。在Druid中,不會存在Oracle下PSCache佔用內存過多的問題,可以把這個數值配置大一些,比如說100
maxOpenPreparedStatements: 100 #要啓用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改爲true。在Druid中,不會存在Oracle下PSCache佔用內存過多的問題,可以把這個數值配置大一些,比如說100
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.mybatisstudy.domain
mapper:
mappers: com.mybatisstudy.dao
not-empty: false
identity: MYSQL
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
returnPageInfo: check
注意:空格代表節點層次;註釋部分用#標記
解釋
- 我們實現的是spring-mybatis的整合,包含mybatis的配置以及datasource數據源的配置當然屬於spring配置中的一部分,所以需要在spring:下。
- mapper-locations相當於XML中的用來掃描Mapper層的配置文件,由於我們的配置文件在resources下,所以需要指定classpath:。
- type-aliases-package相當與XML中別名配置,一般取其下實體類類名作爲別名。
- datasource數據源的配置,name表示當前數據源的名稱,類似於之前的id屬性,這裏可以任意指定,因爲我們無需關注Spring是怎麼注入這個Bean對象的。
- druid代表本項目中使用了阿里的druid連接池,driver-class-name:相當於XML中的
<property
name="driverClassName">;url代表XML中的<property
name="url">;username代表XML中的<property
name="username">;password代表XML中的<property
name="password">;
其他druid的私有屬性配置不再解釋。這裏注意druid連接池和c3p0連接池在XML的的name中就不同,在此處SpringBoot的配置中當然名稱也不同。
如果Spring整合Mybtis的配置你已經很熟悉了,那麼這個配置你肯定也很眼熟,從英文名稱上就很容易區分出來。這裏需要注意的就是YAML語法規定不同行空格代表了不同的層級結構。
既然完成了SpringBoot-Mybatis基本配置下面我們實戰講解如何實現基本的CRUD。其它配置按照相應的格式配置即可
項目結構圖
MyBatis相關
- 配置文件:上面提到,SpringBoot集成MyBatis和SpringMVC集成MyBatis使用上面無太大不同,主要是配置方式不同,上面配置已經介紹
- 數據源配置:DataSourceConfig.java文件中,需要到三個註解
@Configuration
@MapperScan("com.mybatisstudy.dao")
@EnableTransactionManagement
@Configuration
@MapperScan("com.mybatisstudy.dao")
@EnableTransactionManagement
public class DataSourceConfig {
@Autowired
private Environment env;
@Autowired
private PageInterceptor pageInterceptor;
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
fb.setDataSource(dataSource);
//該配置非常的重要,如果不將PageInterceptor設置到SqlSessionFactoryBean中,導致分頁失效
fb.setPlugins(new Interceptor[]{pageInterceptor});
fb.setTypeAliasesPackage(env.getProperty("mybatis.type-aliases-package"));
fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapper-locations")));
return fb.getObject();
}
}
對於@MapperScan 必須寫明,不然DAO層無法到對應的文件.xml文件
Druid相關
Druid配置,數據庫連接池,除了池概念就是sql監控
- 配置文件:yml配置文件中,配置druid內容
- 配置數據源:配置數據源,註解web過濾器,後臺管理的Servlet.在DruidDBConfig.java 文件中配置,主要用@Configuration 註解即可,然後進行配置。
@Configuration
public class DruidDBConfig {
private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean //聲明其爲Bean實例
@Primary //在同樣的DataSource中,首先使用被標註的DataSource
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
//1、配置一個管理後臺的Servlet
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "admin");
initParams.put("allow", "");//默認就是允許所有訪問
initParams.put("deny", "192.168.15.21");//黑名單的IP
bean.setInitParameters(initParams);
return bean;
}
//2、配置一個web監控的filter
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
分頁組件pagehelper相關
- 配置到yml文件:
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
returnPageInfo: check
- 配置註解:
@Configuration
public class PageHelperConfig {
@Value("${pagehelper.helperDialect}")
private String helperDialect;
@Bean
public PageInterceptor pageInterceptor(){
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", helperDialect);
pageInterceptor.setProperties(properties);
return pageInterceptor;
}
}
- 使用:
在dao層,進行查詢的時候,直接調用api,傳入具體參數。
@Override
public List<UserDomain> findAllUser(int pageNum, int pageSize) {
//將參數傳給這個方法就可以實現物理分頁了,非常簡單。
PageHelper.startPage(pageNum, pageSize);
return userDao.selectUsers();
}
在調用數據庫之前,PageHelper.startPage(pageNum, pageSize);非常簡單。如果需要其它功能,可以具體查一下具體api即可。
Controller層:
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserService userService;
@ResponseBody
@PostMapping("/add")
public int addUser(@RequestBody UserDomain user) {
return userService.addUser(user);
}
@ResponseBody
@GetMapping("/all")
public Object findAllUser(@RequestParam(name = "pageNum", required = false, defaultValue = "1") int pageNum,
@RequestParam(name = "pageSize", required = false, defaultValue = "5") int pageSize) {
return userService.findAllUser(pageNum, pageSize);
}
}
注意點:
SpringBoot2中搞清楚視圖層:@RestController 和 @Controller 的區別
- 在springboot中,@RestController 相當於 @Controller + @ResponseBody;
- 即在Controller類中,若想返回jsp或html頁面,則不能用@RestController,只能使用@Controller;
- 若返回的是json或xml數據,可以有兩種寫法:
1. @RestController註解,然後直接return json數據即可;
2. @Controller註解放類之前,然後若類中某個方法需要返回json數據,則需在該方法前添加@ResponseBody註解;
Durid監控
項目跑起來後,我們在durid配置中已經配置了Selevlet的攔截器,並配置了賬號密碼
//1、配置一個管理後臺的Servlet
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "admin");
initParams.put("allow", "");//默認就是允許所有訪問
initParams.put("deny", "192.168.15.21");//黑名單的IP
bean.setInitParameters(initParams);
return bean;
}
直接訪問監控後臺頁面:http://localhost:8081/druid/datasource.html
根據自己設置端口,更改端口。監控極大利於研發人員對性能進行監控,改善系統性能。