博主介绍:💐大家好,我是不行,还得练
博客主页:🔍@不行,还得练的个人主页
————👀努力坚持向技术大牛看齐的菜鸟
————🌊时代浪潮,不进则退
🌸本文章为个人在学习中遇到的困难及解决方案,对学习内容的知识总结等等,希望对您有帮助,初入博客,文章简陋粗浅,如有错误,欢迎批评指正✌
文章目录
前言
本文章将继续对及时项目中所用到的框架进行一个梳理。
一、数据库连接池-Druid
Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池。
1、SpringBoot整合Druid连接池
- 添加依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<!-- springboot3导入如下依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.18</version>
</dependency>
- 配置数据源:
spring:
datasource:
druid:
#配置jdbc连接属性
url:jdbc:mysql://localhost:3306/im_server_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
注意:数据源需要配置在druid下
- 配置连接池:
spring:
datasource:
#配置Druid连接池属性
druid:
#初始化连接数
initial-size: 5
#最小连接池数量
min-idle: 5
#获取连接时最大等待时间,单位毫秒
max-wait: 10000
#连接池最大连接数
max-active: 20
#是否缓存preparedStatement,mysql5.5+建议开启
pool-prepared-statements: true
#缓存的ps最大数量,配置大于0时,pool-prepared-statements属性会自动设置为true
max-pool-prepared-statement-per-connection-size: 20
#用来检测连接是否有效的sql 必须是一个查询语句
validation-query: select 'x'
#检测连接的超时时间
validation-query-timeout: 1000
#申请连接时会执行validation-query检测连接是否有效,开启会降低性能,默认为true
test-on-borrow: false
#归还连接时会执行validation-query检测连接是否有效,开启会降低性能,默认为true
test-on-return: false
2、开启后台监控
spring:
datasource:
druid:
#配置后台监控系统
stat-view-servlet:
#是否开启,默认false
enabled: true
#后台监控系统用户名,默认不需要
login-username: druid
#后台监控系统密码,默认不需要
login-password: druid
#允许访问 - 白名单ip(逗号分隔)
allow: 127.0.0.1,192.168.1.199
#不允许访问 - 黑名单ip(逗号分隔)
#deny:
访问后台监控页面 - http://localhost:8080/druid/index.html
3、开启web应用监控
spring:
datasource:
druid:
#开启web端监控
web-stat-filter:
#开启web监控
enabled: true
#开启session监控
session-stat-enable: true
#session监控的最大数量 - 默认1000
session-stat-max-count: 100
#开启profile-enbale,能够监控单个url的sql列表
profile-enable: true
#排除一些不必要的url
exclusions: /druid/*
#配置session中标识session身份的属性值,用于告诉druid,session的拥有者姓名
#principal-session-name:
#如果用户信息保存在cookie中,则可以通过这个属性配置,告诉druid当前用户是谁
#principal-cookie-name:
4、开启SQL监控
spring:
datasource:
durid:
filter:
stat:
#开启SQL相关统计监控
enabled: true
#数据类型
db-type: mysql
#是否开启慢sql监控
log-slow-sql: true
#慢sql的阈值
slow-sql-millis: 1000
#是否合并sql统计(将不同参数的同一条sql语句合并在一起统计)
merge-sql: off
#统计连接的堆栈追踪数据
connection-stack-trace-enable: true
5、开启防火墙设置
spring:
datasource:
durid:
filter:
wall:
#开启防火墙相关配置
enabled: true
#数据库类型
db-type: mysql
config:
#是否允许执行select *这种sql语句
select-all-column-allow: true
#是否检查SQL语句中where的第一个条件是否永真
select-where-alway-true-check: true
#是否检查SQL语句中having的第一个条件是否永真
select-having-alway-true-check: true
#配置最大返回行数,如果select语句没有指定最大返回行数,会自动修改select添加返回限制
select-limit: 2
#是否允许执行insert语句
insert-allow: true
#限制insert values的大小
insert-values-check-size: 100
#是否检查insert values语法
complete-insert-values-check: true
#是否允许delete语句
delete-allow: false
#是否检查没有where条件的delete语句
delete-where-none-check: true
#是否允许update语句
update-allow: true
#是否检查没有where条件的update语句
update-where-none-check: true
6、开启Spring监控
spring:
datasource:
durid:
#配置mapper层的aop路径
aop-patterns: com.mybatis.mapper.*
7、配置slf4j记录SQL运行日志
spring:
datasource:
durid:
filter:
slf4j:
enabled: true
connection-log-enabled: true
connection-connect-before-log-enabled: true
connection-connect-after-log-enabled: true
connection-commit-after-log-enabled: true
connection-rollback-after-log-enabled: true
statement-executable-sql-log-enable: true
statement-log-enabled: true
同时需要配置一下日志的xml文件(eg: Log4j2.xml)
<appenders>
....
<!-- 这个会打印出所有的SQL指令记录的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="SQLInfoLog" fileName="${FILE_PATH}/${FILE_NAME}_druid_sql.log"
filePattern="${FILE_PATH}/${FILE_NAME}-druid-SQL-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
....
</appenders>
<loggers>
.....
<!-- 记录ken-page的核心日志 -->
<logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="SQLInfoLog"/>
</logger>
.....
</loggers>
二、参数校验
项目中,我们必须对传递过来的参数进行合法性验证,如果参数不合法,那么我们就使用抛异常的方式,告诉方法的调用者传递的参数有问题,这也是 Validated/Valid 数据校验的本质
首先,需要添加validated参数校验依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
常用的校验注解:
1)非空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格
@NotEmpty 检查约束元素是否为NULL或者是EMPTY
2)Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
3)长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) 验证字符串的长度在min和max范围之内.
4)日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期 @Future 验证 Date 和 Calendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期 @Pattern 验证 String 对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式,regexp:正则表达式 flags: 指定 Pattern.Flag 的数组,表示正则表达式的相关选项。
5)数值检查
建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为"“时无法转换为int,但可以转换为Stirng为”",Integer为null
@Min 验证 Number 和 String 对象是否大等于指定的值
@Max 验证 Number 和 String 对象是否小等于指定的值
@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits 验证 Number 和 String 的构成是否合法
@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。
@Range(min=, max=) 被指定的元素必须在合适的范围内
@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)
1.实体类的参数校验
- 在实体类上添加相关注解(eg:NewsInfo)
/**
* 新闻信息表(NewsInfo)表实体类
*
* @author makejava
* @since 2023-10-23 17:16:03
*/
@Data
@Accessors(chain = true)
public class NewsInfo implements Serializable {
//主键 - 选择采用数据库的自动增长
@TableId(type = IdType.AUTO)
private Integer id;
//新闻分类id
@NotNull(message = "新闻分类不能为空!")
private Integer tid;
//新闻标题
@NotBlank(message = "新闻标题不能为空!")
private String subject;
//封面
@Length(min = 6, max = 20, message = "封面的地址长度必须在{min}到{max}之间")
@NotBlank(message = "封面不能为空")
private String fengmian;
//作者
private String writer;
//新闻
@NotBlank(message = "新闻详情不能为空")
private String info;
//发布时间
@DateTimeFormat(pattern = "yyyy-MM-dd")
@NotBlank(message = "发布时间不能为空")
@Future(message = "发布时间不合法")
private Date createTime;
}
- 在控制层实体类参数前添加注解
@PostMapping("/insert")
public R insert(@Validated NewsInfo newsInfo) {
boolean save = newsInfoService.save(newsInfo);
return R.succ(save);
}
- 在全局异常处理中自定义异常处理
@ExceptionHandler(MethodArgumentNotValidException.class)
public R parasValiteHandler(MethodArgumentNotValidException e){
List<String> errorInfos = e.getBindingResult()
.getAllErrors().stream()
.map(objectError -> objectError.getDefaultMessage())
.collect(Collectors.toList());
return R.fail(Codes.VAILTE_ERROR, errorInfos);
}
2.形式参数的参数校验
- 在参数上添加注解
public R login(@NotBlank(message = "用户名不能为空!") String username,
@NotBlank(message = "密码不能为空!")
@Length(min = 6, max = 20, message = "密码长度不正确") String password)
- 在控制层类上添加校验注解
@Validated
public class NewsInfoController
- 在全局异常处理中自定义异常处理
/**
* 形参的参数校验异常
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
public R paramsValdateHandler(ConstraintViolationException e){
List<String> result = e.getConstraintViolations().stream()
.map(constraintViolation -> constraintViolation.getMessage())
.collect(Collectors.toList());
return R.fail(Codes.VAILTE_ERROR, result);
}
三、配置jackson的输出格式
指定输出时的格式
spring:
jackson:
#返回的json数据自动过滤null的属性
default-property-inclusion: non_null
#指定返回的时间格式
date-format: yyyy-MM-dd HH:mm:ss
#指定时区
time-zone: GMT+8
四、事务管理
- 在启动类中添加事务开启注解
@EnableTransactionManagement
public class ImServerApplication {
}
- 直接在需要事务的业务方法上添加注解
@Transactional
public boolean save(NewsInfo entity) {
}
- @Transation注解可以标记在业务类上,表示类中的所有业务方法都需要进行事务管理
- 该注解默认只会回滚运行时异常
- 标记该注解的业务方法不能自行捕获异常,如果需要处理异常,也应该在最后手动将异常抛给Spring
- @Transactional(rollbackFor = Exception.class) 表示回滚所有异常
五、BaseController的封装
仿照MybatisPlus的做法把在controller层自动装配的service层进行一个封装
- 创建一个BaseController类进行封装方法
public class BaseController<T> {
@Autowired
private T service;
public T getBaseService(){
return service;
}
}
- 在需要自动装配的controller类中直接继承BaseController类
在类中直接通过getBaseService方法调用相应Service中的方法
public class UserController extends BaseController<UserService> {
@PostMapping("/register")
public R register(@Validated User user) {
log.debug("【User Register】用户注册...{}", user);
//调用业务层保存用户信息
getBaseService().save(user);
return R.succ();
}
}
总结
至此,本项目的大概框架就搭建好了,接下来,就可以根据需求进行具体的项目的开发了