即时通信项目2-架构搭建

博主介绍:💐大家好,我是不行,还得练
博客主页:🔍@不行,还得练的个人主页
————👀努力坚持向技术大牛看齐的菜鸟
————🌊时代浪潮,不进则退
🌸本文章为个人在学习中遇到的困难及解决方案,对学习内容的知识总结等等,希望对您有帮助,初入博客,文章简陋粗浅,如有错误,欢迎批评指正✌


前言

本文章将继续对及时项目中所用到的框架进行一个梳理。


一、数据库连接池-Druid

Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池。

1、SpringBoot整合Druid连接池

  1. 添加依赖:
<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>
  1. 配置数据源:
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下

  1. 配置连接池:
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:

web监控
web监控2

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.*

Spring监控

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.实体类的参数校验

  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;
}
  1. 在控制层实体类参数前添加注解
@PostMapping("/insert")
public R insert(@Validated NewsInfo newsInfo) {
    boolean save = newsInfoService.save(newsInfo);
    return R.succ(save);
}
  1. 在全局异常处理中自定义异常处理
@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.形式参数的参数校验

  1. 在参数上添加注解
 public R login(@NotBlank(message = "用户名不能为空!") String username,
           @NotBlank(message = "密码不能为空!")
           @Length(min = 6, max = 20, message = "密码长度不正确") String password)
  1. 在控制层类上添加校验注解
@Validated
public class NewsInfoController
  1. 在全局异常处理中自定义异常处理
/**
 * 形参的参数校验异常
 * @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

四、事务管理

  1. 在启动类中添加事务开启注解
@EnableTransactionManagement
public class ImServerApplication {
    
}
  1. 直接在需要事务的业务方法上添加注解
@Transactional
public boolean save(NewsInfo entity) {

}
  • @Transation注解可以标记在业务类上,表示类中的所有业务方法都需要进行事务管理
  • 该注解默认只会回滚运行时异常
  • 标记该注解的业务方法不能自行捕获异常,如果需要处理异常,也应该在最后手动将异常抛给Spring
  • @Transactional(rollbackFor = Exception.class) 表示回滚所有异常

五、BaseController的封装

仿照MybatisPlus的做法把在controller层自动装配的service层进行一个封装

  1. 创建一个BaseController类进行封装方法
public class BaseController<T> {

    @Autowired
    private T service;

    public T getBaseService(){
        return service;
    }
}
  1. 在需要自动装配的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();
    }
}


总结

至此,本项目的大概框架就搭建好了,接下来,就可以根据需求进行具体的项目的开发了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值