百日筑基第十一天-看看SpringBoot

百日筑基第十一天-看看SpringBoot

创建项目

Spring 官方提供了 Spring Initializr 的方式来创建 Spring Boot 项目。网址如下:

https://start.spring.io/

打开后的界面如下:

在这里插入图片描述

可以将 Spring Initializr 看作是 Spring Boot 项目的初始化向导,它可以帮助开发人员在一分钟之内创建一个 Spring Boot 骨架,非常的傻瓜式。

来解释一下 Spring Initializr 初始化界面中的关键选项。

1)Project:项目的构建方式,可以选择 Mavenopen in new window(安装方式可以戳链接) 和 Gradle(构建脚本基于 Groovy 或者 Kotlin 等语言来编写,而不是传统的 XML)。编程喵默认采用的 Maven。

2)Language:项目的开发语言,可以选择 Java、Kotlin(JetBrains开发的可以在 JVM 上运行的编程语言)、Groovy(可以作为 Java 平台的脚本语言来使用)。默认 Java 即可。

3)Spring Boot:项目使用的 Spring Boot 版本。默认版本即可,比较稳定。

4)Project Metada:项目的基础设置,包括包名、打包方式、JDK 版本等。

  • Group:项目所属组织的标识符,比如说 top.codingmore;
  • Artifact:项目的标识符,比如说 coding-more;
  • Name:默认保持和 Artifact 一致即可;
  • Description: 项目的描述信息,比如说《编程喵实战项目(Spring Boot+Vue 前后端分离项目)》;
  • Package name:项目包名,根据Group和Artifact自动生成即可。
  • Packaging: 项目打包方式,可以选择 Jar 和 War(SSM 时代,JavaWeb 项目通常会打成 War 包,放在 Tomcat 下),Spring Boot 时代默认 Jar 包即可,因为 Spring Boot 可以内置 Tomcat、Jetty、Undertow 等服务容器了。
  • Java:项目选用的 JDK 版本。

5)Dependencies:项目所需要的依赖和 starter。如果不选择的话,默认只有核心模块 spring-boot-starter 和测试模块 spring-boot-starter-test。

生成zip文件解压:

在这里插入图片描述

重要的包

spring-boot-devtools 热部署

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId>
</dependency>

整合Lombok简化代码

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.6</version><scope>provided</scope>
</dependency>

然后就可以这样用了:

@Getter
@Setter
class CmowerLombok {private int age;private String name;private BigDecimal money;
}

其中 scope=provided,就说明 Lombok 只在编译阶段生效。也就是说,Lombok 会在编译期静悄悄地将带 Lombok 注解的源码文件正确编译为完整的 class 文件。

SpringBoot 2.1.x 版本后不需要再显式地添加 Lombok 依赖了。之后,还需要为 Intellij IDEA 安装 Lombok 插件,否则 Javabeangetter / setter 就无法自动编译,也就不能被调用。不过,新版的 Intellij IDEA 也已经内置好了,不需要再安装。

@Getter / @Setter 用起来很灵活,比如说像下面这样:

class CmowerLombok {@Getter @Setter private int age;@Getter private String name;@Setter private BigDecimal money;
}

@ToString 注解可以生成 toString 方法:

@ToString
class CmowerLombok {private int age;private String name;private BigDecimal money;
}

@Data 注解可以生成 getter / setterequalshashCode,以及 toString,是个总和的选项。

@Data
class CmowerLombok {private int age;private String name;private BigDecimal money;
}

@Slf4j 可以用来生成注解对象,你可以根据自己的日志实现方式来选用不同的注解,比如说:@Log@Log4j@Log4j2@Slf4j 等。

@Slf4j
public class Log4jDemo {public static void main(String[] args) {log.info("level:{}","info");log.warn("level:{}","warn");log.error("level:{}", "error");}
}

@Builder 注解可以用来通过建造者模式来创建对象,这样就可以通过链式调用的方式进行对象赋值,非常的方便。

@Builder
@ToString
public class BuilderDemo {private Long id;private String name;private Integer age;public static void main(String[] args) {BuilderDemo demo = BuilderDemo.builder().age(18).name("沉默王二").build();System.out.println(demo);}
}

Lombok 还提供了同步注解 @Synchronized、自动抛出异常注解 @SneakyThrows、不可变对象 @Value、自动生成 hashCode 和 equals 方法的注解 @EqualsAndHashCode等等,

Lombok 用起来虽然爽,但需要团队内部达成一致,就是要用大家都用,否则有些用了有些没用就会乱成一锅粥,很影响代码的整体风格。

整合 MySQL 和 Druid

Mysql

对应pom.xml文件中的代码:

<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>
</dependency>

在 application.yml 文件中添加数据库链接驱动信息:

spring:datasource:username: codingmore-mysqlpassword: YyfR4TDxCwrjZ2Fsurl:jdbc: mysql://118.190.99.232:3306/codingmore-mysql?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
@SpringBootTest
@Slf4j
class CodingmoreMysqlApplicationTests {@Resourceprivate JdbcTemplate jdbcTemplate;@Testvoid contextLoads() {String sql ="select * from user";List<User> users = jdbcTemplate.query(sql, new RowMapper<User>() {@Overridepublic User mapRow(ResultSet rs, int rowNum) throws SQLException {User user = new User();user.setId(rs.getInt(1));user.setAge(rs.getInt("age"));user.setName(rs.getString("name"));user.setPassword(rs.getString("password"));return user;}});log.info("查询成功");log.info("用户{}",users);}
}

Spring Boot 的测试类主要放置在 src/test/java 目录下面,项目创建成功后,Spring Boot 会根据项目名称自动为我们生成测试类。

比如说本次项目名为 codingmore-mysql,那么测试类名为 CodingmoreMysqlApplicationTests。

@SpringBootTest 注解能够测试我们的项目主类,该项目为 CodingmoreMysqlApplication。

@Test 注解是 junit 单元测试的注解,表示该方法为测试方法。

JdbcTemplate 一个通过 JDBC 连接数据库的工具类,spring-boot-starter-jdbc 依赖中包含了该类。

@Resource 注解会帮我们在 Spring Boot 启动的时候注入一个 JdbcTemplate 的对象。

jdbcTemplate.query() 方法通过 SQL 语句和匿名内部类参数的形式,执行 SQL 并查询结果集。

RowMapper 就是查询到的每一行数据对象,我们可以通过重写 mapRow 方法将数据结果集封装到 User 对象上。

Druid

Druid 是阿里巴巴开源的一款数据库连接池,结合了C3P0、DBCP 等 DB 池的优点,同时还加入了日志监控。

Druid 包含了三个重要的组成部分:

  • DruidDriver,能够提供基于 Filter-Chain 模式的插件体系;
  • DruidDataSource,高效可管理的数据库连接池;
  • SQLParser,支持所有 JDBC 兼容的数据库,包括 Oracle、MySQL 等。

第一步,在 pom.xml 文件中添加 Druid 的依赖,官方已经提供了 starter,我们直接使用。

<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.23</version>
</dependency>

第二步,在 application.yml 文件中添加 Druid 配置。

spring:datasource:    type: com.alibaba.druid.pool.DruidDataSourcedruid:#初始化连接池大小initial-size: 5#配置最小连接数min-idle: 5#配置最大连接数max-active: 200#配置连接等待超时时间max-wait: 60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒time-between-eviction-runs-millis: 60000#配置一个连接在池中最小生存的时间,单位是毫秒min-evictable-idle-time-millis: 300000#测试连接validation-query: SELECT 1 FROM DUAL#申请连接的时候检测,建议配置为true,不影响性能,并且保证安全test-while-idle: true#获取连接时执行检测,建议关闭,影响性能test-on-borrow: false#归还连接时执行检测,建议关闭,影响性能test-on-return: false#是否开启PSCache,PSCache对支持游标的数据库性能提升巨大,oracle建议开启,mysql下建议关闭pool-prepared-statements: false#开启poolPreparedStatements后生效max-pool-prepared-statement-per-connection-size: 20#配置扩展插件,常用的插件有=>stat:监控统计  log4j:日志  wall:防御sql注入filters: stat,wall,slf4j#打开mergeSql功能;慢SQL记录connection-properties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000#配置DruidStatFilterweb-stat-filter:enabled: trueurl-pattern: "/*"exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"#配置DruidStatViewServletstat-view-servlet:url-pattern: "/druid/*"#登录名login-username: root#登录密码login-password: root

第三步,启动项目。在日志信息里可以看到 Druid 的初始化信息。

在这里插入图片描述

第四步,通过 http://localhost:9002/druid/ 地址就可以在浏览器访问 Druid 的监控页面了,用户名和密码是我们在配置文件里指定的 root 和 root,登录后是这样的。

在这里插入图片描述

Spring 对事务的支持

Spring 支持两种事务方式,分别是编程式事务和声明式事务,后者最常见,通常情况下只需要一个 @Transactional 就搞定了(代码侵入性降到了最低),就像这样:

@Transactional
public void savePosts(PostsParam postsParam) {// 保存文章save(posts);// 处理标签insertOrUpdateTag(postsParam, posts);
}

1)编程式事务

编程式事务是指将事务管理代码嵌入嵌入到业务代码中,来控制事务的提交和回滚。

你比如说,使用 TransactionTemplate 来管理事务:

@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {try {// ....  业务代码} catch (Exception e){//回滚transactionStatus.setRollbackOnly();}}});
}

再比如说,使用 TransactionManager 来管理事务:

@Autowired
private PlatformTransactionManager transactionManager;public void testTransaction() {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// ....  业务代码transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}
}

就编程式事务管理而言,Spring 更推荐使用 TransactionTemplate。

在编程式事务中,必须在每个业务操作中包含额外的事务管理代码,就导致代码看起来非常的臃肿,但对理解 Spring 的事务管理模型非常有帮助。

2)声明式事务

声明式事务将事务管理代码从业务方法中抽离了出来,以声明式的方式来实现事务管理,对于开发者来说,声明式事务显然比编程式事务更易用、更好用。

当然了,要想实现事务管理和业务代码的抽离,就必须得用到 Spring 当中最关键最核心的技术之一,AOP,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚。

声明式事务虽然优于编程式事务,但也有不足,声明式事务管理的粒度是方法级别,而编程式事务是可以精确到代码块级别的

Spring Boot 对事务的支持

只需要在业务层添加事务注解(@Transactional)就可以快速开启事务。

也就是说,我们只需要把焦点放在 @Transactional 注解上就可以了。

@Transactional 的作用范围

  • 类上,表明类中所有 public 方法都启用事务
  • 方法上,最常用的一种
  • 接口上,不推荐使用

@Transactional 的常用配置参数

虽然 @Transactional 注解源码中定义了很多属性,但大多数时候,我都是采用默认配置,当然了,如果需要自定义的话,前面也都说明过了。

@Transactional 的使用注意事项总结

1)要在 public 方法上使用,在AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断,如果目标方法不是public,则TransactionAttribute返回null,即不支持事务。

2)避免同一个类中调用 @Transactional 注解的方法,这样会导致事务失效。

过滤器、拦截器、监听器

  • 过滤器(Filter):当有一堆请求,只希望符合预期的请求进来。
  • 拦截器(Interceptor):想要干涉预期的请求。
  • 监听器(Listener):想要监听这些请求具体做了什么。
过滤器
  • 过滤敏感词汇(防止sql注入)
  • 设置字符编码
  • URL级别的权限访问控制
  • 压缩响应信息

添加一个过滤器 MyFilter :

@WebFilter(urlPatterns = "/*", filterName = "myFilter")
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {long start = System.currentTimeMillis();chain.doFilter(request,response);System.out.println("Execute cost="+(System.currentTimeMillis()-start));}@Overridepublic void destroy() {Filter.super.destroy();}
}

@WebFilter 注解用于将一个类声明为过滤器,urlPatterns 属性用来指定过滤器的 URL 匹配模式,filterName 用来定义过滤器的名字。

MyFilter 过滤器的逻辑非常简单,重写了 Filter 的三个方法,在 doFilter 方法中加入了时间戳的记录。然后我们在项目入口类上加上 @ServletComponentScan 注解,这样过滤器就会自动注册。

拦截器
  • 登录验证,判断用户是否登录
  • 权限验证,判断用户是否有权限访问资源,如校验token
  • 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量
  • 处理cookie、本地化、国际化、主题等
  • 性能监控,监控请求处理时长等
@Slf4j
public class LoggerInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("preHandle{}...",request.getRequestURI());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

一个拦截器必须实现 HandlerInterceptor 接口,preHandle 方法是 Controller 方法调用前执行,postHandle 是 Controller 方法正常返回后执行,afterCompletion 方法无论 Controller 方法是否抛异常都会执行。

只有 preHandle 返回 true 的话,其他两个方法才会执行。

如果 preHandle 返回 false 的话,表示不需要调用Controller方法继续处理了,通常在认证或者安全检查失败时直接返回错误响应。

再来一个 InterceptorConfig 对拦截器进行配置:

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoggerInterceptor()).addPathPatterns("/**");}
}

@Configuration 注解用于定义配置类,干掉了以往 Spring 繁琐的 xml 配置文件。

编写一个用于被拦截的控制器 MyInterceptorController:

@RestController
@RequestMapping("/myinterceptor")
public class MyInterceptorController {@RequestMapping("/hello")public String hello() {return "沉默王二是傻X";}
}

@RestController 注解相当于 @Controller + @ResponseBody 注解,@ResponseBody 注解用于将 Controller 方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区,通常用来返回 JSON 或者 XML 数据,返回 JSON 数据的情况比较多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/40988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数智化人物展】数势科技创始人兼CEO黎科峰:数智化时代To B软件行业面临颠覆与重塑...

黎科峰 本文由数势科技创始人兼CEO黎科峰投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 2020年&#xff0c;对我而言&#xff0c;是职业生涯中的一个重大转折点。在全球新…

FPGA/数字IC复习八股

一、FPGA概念&#xff0c;与数字IC的区别 二、FPGA底层逻辑 三、同步电路、异步电路以及优缺点 四、同步复位、异步复位、异步复位同步释放 深入理解复位---同步复位&#xff0c;异步复位&#xff0c;异步复位同步释放(含多时钟域&#xff09;_画出支持异步复位dff的电路图…

CourseDetail

目录 1、 CourseDetail.cshtml 1.1、 Content body start 1.2、 <!-- row --> 1.3、 Content body end CourseDetail.cshtml@{Layout = "_Admin

使用css,让div消失在视野中的方法

使用css&#xff0c;让div消失在视野中的方法 display: none;visibility: hidden;opacity:0;通过定位隐藏元素通过margin隐藏元素 display: none; display:none是彻底消失&#xff0c;不在文档流中占位&#xff0c;浏览器也不会解析该元素&#xff1b; 如果给一个元素设置了d…

频域信号通过逆傅里叶变换恢复成时域信号

频域信号通过逆傅里叶变换恢复成时域信号 flyfish import numpy as np import matplotlib.pyplot as plt from scipy.fftpack import fft, ifft plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False# 设置参数 t np.linspace(0, 1, 1000, en…

Google XTS 问题解决 | Android 设备认证

XTS介绍 https://source.android.com/docs/compatibility/cts?hlzh-cn CTS (Compatibility Test Suite) &#xff1a; 兼容性测试套件&#xff0c;主要 google 为保证 Android 核心接口功能的 兼容性。GTS &#xff08; google test suite &#xff09;&#xff1a; Google…

pytorch pnnx repvit模型转换

先把模型转到libtorch #!/usr/bin/env python3 # -*- coding:utf-8 -*- import argparse import time import sys import os import torch import torch.nn as nn import torch.backends.cudnn as cudnn from timm.models import create_model import time import modelinput_…

Django权限系统如何使用?

Django的权限系统是一个强大而灵活的特性&#xff0c;允许你控制不同用户对应用程序中资源的访问。以下是使用Django权限系统的几个基本步骤&#xff1a; 1. 定义模型权限 在你的models.py文件中&#xff0c;你可以为每个模型定义自定义权限。这通过在模型的Meta类里设置perm…

Simulink中示波器连续运行的方法

1.在Simulink中,经常要使用到示波器,默认示波器是定时运行的,只能观察到一小部分运行的波形;实际调试过程中,经常要连续运行,因此,需要设置示波器为连续运行模式,下面将介绍示波器连续运行的方法。 打开Simulink仿真软件,找到仿真设置按钮,点击设置: 2.将其停止时间…

实现一个优雅的 jsBridge 方案

实现一个优雅的 jsBridge 方案 在 iOS 项目中&#xff0c;有时需要实现 JavaScript 和 Native 代码之间的通信。本文介绍一种优雅的 jsBridge 实现方案&#xff0c;支持互相调用和回调机制&#xff0c;并附带详细的代码和注释。 步骤 1: 定义桥接协议 首先&#xff0c;定义一…

音频流格式启用数据流

音频流格式启用数据流 音频流格式启用数据流使用 AudioStreamBasicDescription 结构在哪里以及如何设置流格式 音频流格式启用数据流 在单个样本帧级别处理音频数据时&#xff0c;就像使用音频单元一样&#xff0c;仅仅指定正确的数据类型来表示音频是不够的。单个音频样本值中…

Vuetify3:Vuetify3 + Nuxt3时 tabs 跳转页面

在一开始没去看vuetify3的文档直接使用了nuxt3跳转方式 <template><v-tabs><NuxtLink :to"/yourRouter"><v-tab to"/tab1">Tab 1</v-tab></NuxtLink><v-tab to"/tab2"><NuxtLink :to"/yourR…

升级confluence中的内嵌tomcat

步骤&#xff1a; 1、下载新版本tomcat 下载地址&#xff1a;https://tomcat.apache.org/download-90.cgi 2、关闭confluence 进入confluence的bin目录&#xff0c;执行./stop-confluence.sh 3、备份confluence 在对应目录下&#xff0c;执行 cp ./confluence -r ./conflu…

HandlerMethodArgumentResolver :深入spring mvc参数解析机制

❃博主首页 &#xff1a; <码到三十五> ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a; 搬的每块砖&#xff0c;皆为峰峦之基&#xff1b;公众号搜索(码到三十…

编程新纪元:AI辅助工具豆包Marscode体验

自从ChatGPT带动全球AI热潮&#xff0c;AI席卷着各行各业。编程界也不例外&#xff0c;早期做过了Github Copilot、阿里的通义灵码等AI编程插件的体验 p.s.以上的下载量与评分均只是plugins.jetbrains的marketplace数据&#xff0c;仅供参考 基本AI编程工具的功能都差不多&…

目标检测中的mAP计算:深入解析与实践指南

目标检测中的mAP计算&#xff1a;深入解析与实践指南 在目标检测任务中&#xff0c;评估模型性能是一个复杂的过程&#xff0c;因为需要同时考虑检测的准确性和召回率。平均精度均值&#xff08;mean Average Precision&#xff0c;简称mAP&#xff09;是一个广泛使用的评估指…

自然语言处理学习(3)RNN 模型学习---NLP领域的第一个模型

一 基本定义 视频链接 1.小案例理解–语义理解 目的&#xff1a;输入一句话&#xff0c;机器需要理解这句话的语义 二. RNN模型分类 1. 按照输入输出分类 (1) N Vs N (2) N Vs 1 (3) 1 VsN (4) seq2seq 三 传统RNN模型 1. 内部结构分析 &#xff08;a) 总体外…

基于单片机的多功能电子时钟的设计

摘要&#xff1a;提出了一种基于单片机的多功能电子时钟的设计方法&#xff0c;以 AT89C52单片机作为系统的主控芯片&#xff0c;采用DS1302作为时钟控制芯片&#xff0c;实现日期时钟显示并且提供精准定时的功能。此外&#xff0c;还可经由DHT22所构成的温湿度传感电路&#x…

Kafka集群部署(手把手部署图文详细版)

1.1.1 部署zookpeer 在node02下载并解压zookeeper软件包 cd /usr/local wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz 或者&#xff1a;scp cat192.168.28.100:/home/cat/zookeeper-3.4.6.tar.gz /tmp&#xff08;注意目录&#xf…

vue属性绑定v-bind

属性绑定v-bind 双大括号不能在HTML attributes 中使用。想要响应式地绑定一个attribute&#xff0c;应该使用v-bind指令。 v-bind 指令指示Vue将元素id attribute 与组件的dyid属性保持一致。如果绑定值是null或者undefined&#xff0c;那么该attribute将会从渲染的元素上移…