Springboot与各组件之间的整合
方式一----继承
通过idea创建springboot项目,可以根据需要去选择要配置的一些组件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gavin.springbootmybatis</groupId>
<artifactId>springbootbatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootbatis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<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.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<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>
这种方式是通过继承父类来实现的;
方式二—引入独立依赖
手动引入mybatis依赖,web依赖即可
为什么我不建议初学者直接使用第一种方式?
1,虽然第一种方式方便快捷,但是毕竟是初学者,还是要搞懂原理;
2,另外,第一种方式是继承父类的,不便于后期功能扩展;
下面分析一下第二种方式,
首先搭建springboot项目,无论是springbootweb还是springbootmybatis,甚至springbootjdbc,最基本的是springboot这个基石;
第一步:建立一个maven项目
第二步:引入基本的springboot依赖
然后在引入需要的启动器---->
web启动器/mybatis启动器/jdbc启动器(按需导入,这里一次性导入了.)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
在这里我们可以看到启动器的命名规则上有一些区别------->>
一般来讲,官方的启动器命名规则是spring-boot-starter-** 在前,而第三方的是 **-spring-boot-starter;
springboot与mybatis整合案例
依赖分析---->可以看到相关的jdbc由于依赖关联而被自动导入;
并没有导入mysql的驱动
之后按照需求导入
准备pojo类
package com.gavin.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* user
* @author
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private Integer id;
private String name;
private String pwd;
private String nickname;
private String picname;
private String filetype;
private static final long serialVersionUID = 1L;
}
运行结果
注意的点:Mapper注解告诉容器该类是mybatis的接口
如果不写这个还可以在启动类上添加包扫描来实现
@MapperScan,该注解下有很多参数,
最基本的value, basePackage,以及basePackageClasses等;
总结------>>
1,导入根基依赖spring-boot
2,按需导入其他依赖
3,检查其他依赖,着重检查可变依赖-----比如数据库依赖
4,配置依赖参数
5,编写相关类
springboot整合日志记录
在springboot中不需要在单独导入log4j等日志记录依赖,因为在springboot中有专门的用于日志的记录组件----logback
logback读取配置文件的步骤----->
1,在classpath下查找文件 logback-test.xml
2,如果文件不存在,则查找logback.xml
logback配置文件— 模板
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="${catalina.base}/logs/"/>
<!-- 控制台输出 -->
<appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日志输出格式 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>/server.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 异常日志文件 -->
<appender name="error_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/error/error.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>500MB</MaxFileSize>
</triggeringPolicy>
<!-- 只打印错误日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--连接数据库配置-->
<appender name="db_classic_mysql_pool" class="ch.qos.logback.classic.db.DBAppender">
<connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
<dataSource class="org.apache.commons.dbcp.BasicDataSource">
<driverClassName>com.mysql.cj.jdbc.Driver</driverClassName>
<url>jdbc:mysql://127.0.0.1:3306/gavin?serverTimezone=Asia/Shanghai</url>
<username>gavin</username>
<password>955945</password>
</dataSource>
</connectionSource>
</appender>
<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="warn"/>
<logger name="java.sql.Connection" level="warn" />
<logger name="java.sql.Statement" level="warn"/>
<logger name="java.sql.PreparedStatement" level="warn"/>
<!-- 日志输出级别 -->
<root level="debug">
<appender-ref ref="Stdout"/>
<appender-ref ref="RollingFile"/>
<appender-ref ref="error_file"/>
<appender-ref ref="db_classic_mysql_pool"/>
</root>
<logger name="com.gavin.mapper" level="DEBUG"></logger>
</configuration>
注意---->>日志记录过程需要 还需要以下几个依赖
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- logback -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
少了一些依赖就会报一些错误,比如 ***** null 或者初始化的时候找不到…或者初始化失败;
最好的方式是把每一个依赖都去掉看看会报什么错;这里不在演示了;
别着急,如果配置了异步写入数据库,那么数据往哪里写?数据写入的字段又是些什么?
这个在依赖的jar包里有答案—
按照给出的sql语句创建sql表,然后执行springboot
SpringBoot分页实现
回顾一下springweb中的分页实现
在springweb中实现分页还是比较繁琐的,前端需要向后端发送页数以及页大小等信息然后后端需要向数据库查询,在去做处理;
在springboot中正常的查询业务只需要加上一行代码即可实现分页所需;
pagehelpers 的实现原理----->>
其在方法内使用了静态ThreadLocal参数,分页的参数和线程是绑定的,
ThreadLocal设置分页参数(pageindex,pagesize),
查询时获取参数
通过拦截器在sql中添加sql语句分业务数据参数,
实现分页查询
最后清除查询参数
案例演示---->>
准备数据库表格----->>goods表
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
`id` int NOT NULL AUTO_INCREMENT,
`goodsName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`price` float NULL DEFAULT NULL,
`goodsDesc` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES (3, '宫保鸡丁', 21, '宫保鸡丁哦');
INSERT INTO `goods` VALUES (5, '青椒肉丝', 22, '青椒肉丝不好吃');
INSERT INTO `goods` VALUES (8, '地三鲜', 15, '酸甜口');
INSERT INTO `goods` VALUES (9, '鱼香肉丝', 9, '四川风味');
INSERT INTO `goods` VALUES (10, '回锅肉', 12, '辣味');
INSERT INTO `goods` VALUES (11, '热狗肠', 32, '纯瘦肉版');
INSERT INTO `goods` VALUES (12, '烧花鸭', 56, '河南黄鸭');
INSERT INTO `goods` VALUES (13, '焖鸭掌', 35, '芦花鸭');
INSERT INTO `goods` VALUES (14, '肥肠鱼', 46, '香辣');
INSERT INTO `goods` VALUES (15, '松花小肚', 88, '猪肚');
INSERT INTO `goods` VALUES (16, '炸花生米', 12, '大花生');
INSERT INTO `goods` VALUES (17, '清蒸鲈鱼', 34, '海鲈鱼');
SET FOREIGN_KEY_CHECKS = 1;
添加pagehelper依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
编辑查询方法 查询方法不在这里赘述,直接看结果
接下来就是实现分页数据
添加分页查询相关的方法
@Service
public class GoodsServiceImp implements GoodsService {
@Autowired
private GoodsMapper goodsMapper;
@Override
public List<Goods> showGoods() {
return goodsMapper.findGoods();
}
@Override
public List<Goods> findByPage(Integer pageNum, Integer pageSize) {
//将分页数据传入
PageHelper.startPage(pageNum,pageSize);
//这样查询数据时会按照页进行查询
return goodsMapper.findGoods();
}
}
首先先将pagehelper部分注释掉,
接下来对比一下
在没有添加pagehelper时,执行的sql语句---->>
[http-nio-8080-exec-1] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
[http-nio-8080-exec-1] INFO org.springframework.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
[http-nio-8080-exec-1] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 1 ms
[http-nio-8080-exec-1] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
[http-nio-8080-exec-1] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
[http-nio-8080-exec-1] DEBUG com.gavin.mapper.GoodsMapper.findGoods - ==> Preparing: select id, goodsName, price, goodsDesc from goods
[http-nio-8080-exec-1] DEBUG com.gavin.mapper.GoodsMapper.findGoods - ==> Parameters:
[http-nio-8080-exec-1] DEBUG com.gavin.mapper.GoodsMapper.findGoods - <== Total: 12
1,实例化DispatcherServlet
Initializing Spring DispatcherServlet ‘dispatcherServlet’
2,数据库连接池初始化
com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
3,查询数据库
Preparing: select id, goodsName, price, goodsDesc from goods
在有pagehelper是我们再看
查询非第一页时
前端还可以接收到哪些信息呢?
PageHelper.startPage()方法是带有返回值的,
Page<Goods> goodsPage = PageHelper.startPage(pageNum, pageSize);
返回值都包含哪些信息呢?找到page类去看一下
包含很多信息,我们都可以通过get方法来获取
System.out.println(goodsPage);
System.out.println("---------------------");
System.out.println("当前页--" + goodsPage.getPageNum());
System.out.println("总页--" + goodsPage.getPages());
System.out.println("页大小--" + goodsPage.getPageSize());
System.out.println("总记录数--" + goodsPage.getTotal());
System.out.println("当前页数据--" + goodsPage.getResult());
但是这些数据在查询完毕后就会被清除掉,要想保存下来,那么就需要将这些信息给封装起来
PageInfo<Goods> pageInfo= new PageInfo<>(goodsPage);
System.out.println("当前页"+pageInfo.getPageNum());
System.out.println("总页数"+pageInfo.getPages());
System.out.println("页大小"+pageInfo.getSize());
System.out.println("总记录数"+pageInfo.getTotal());
System.out.println("当前页数据"+pageInfo.getList());
所以如果想要持久化保存分页数据以便前端能够用到,那么可以将返回值改为pageInfo
依赖分析---->>
Springboot与Druid整合
其实很简单,就是把Druid启动器添加到依赖然后将原来jdbc连接池的部分替换为druid即可;
为什么要使用Druid连接池?在这篇文章中已经详细阐述了
阿里的德鲁伊怎么玩?
引入druid启动器
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
看一下该依赖的依赖传递关系
接下来是配Druidpool,
spring:
datasource:
# type表示不在使用spring内部的连接池,而是使用阿里的Druid连接池
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
# 填写你数据库的url、登录名、密码和数据库名
url: jdbc:mysql://127.0.0.1:3306/gavin?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: gavin
password: 123456
druid:
# 连接池的配置信息
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
启动项目
访问一下druid控制台
奇怪的事情又发生了,发生了404
404-找不到,这是什么原因?
经排查是依赖的版本的问题,druid的版本太高了,
发现1.10版本可以正常访问,不太清楚什么原因
druid连接池可以做一些列参数设定;
当设定192.168.135.145(虚拟机IP地址)可以访问druid控制台时.
当禁用192.168.135.145(虚拟机IP地址)访问时—>
发现并没有生效,这是为什呢?
排查后发现少了一个参数enable
如果不配置这个,则默认的为false,即谁都可以访问,
所以要配置enable为true使关于ip配置生效;
如果没有另一方式是通过配置类来实现 ,原理是通过StatViewServlet去处理IP地址;
package com.gavin.controller;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Gavin
*/
@Configuration
public class DruidConfiguration {
@Bean
public ServletRegistrationBean<StatViewServlet> statViewServlet() {
ServletRegistrationBean<StatViewServlet> srb = new ServletRegistrationBean
(new StatViewServlet(), "/druid/*");
//IP白名单(没有配置或者为空,则允许所有访问)
srb.addInitParameter("allow", "127.0.0.1");
//IP黑名单(黑白均有时,deny优先于allow) :
//如果满足deny的即提示:Sorry, you are not permitted to view this page.
srb.addInitParameter("deny", "192.168.135.145");
//账号参数名必须为loginUsername
srb.addInitParameter("loginUsername", "admin");
//密码参数名必须为loginPassword
srb.addInitParameter("loginPassword", "123456");
//是否能够重置数据
srb.addInitParameter("resetEnable", "false");
return srb;
}
}
然后将配置文件中的关于权限的部分注释掉,这样通过后端来限制并作出相应反馈处理;
Springboot整合jsp-----[旧技术]
引入jsp依赖
<!--JSP依赖-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
编写controller,并访问,duanduanduang
啥情况?
oh,我这个工程是一个聚合工程,因此需要设置一下使得jsp生效;
设置之后
jsp就到这里吧;