目录
一、基础篇(未完随时补充):
1.常用注解:
二、运维实用篇
1. 程序为什么打包
2. 配置高级
3. 多环境开发
三、开发实用篇:
1.热部署
(1)何为热部署
(2)中心思想
(3)怎么添加热部署
2. 配置高级
(1)@ConfigurationProperties
(2)宽松绑定/松散绑定
(3)常用计量单位绑定
(4)数据校验
3. 测试
(1)加载测试专用属性
(2)加载测试专用配置
(3)Web环境模拟测试
(4) 发送虚拟请求
(5)数据层测试回滚 (@Transactional)
(6)测试用例设置随机数据
4. 数据层解决方案
(1)SQL
(2)NoSQL--Redis
@SpringBootApplication 定位主类
@Configuration 表明一个类中声明一个和多个@Bean标记的方法,并且这些方法被Spring容器管理用于生成Bean定义以及在运行时这些Bean的服务请求
@ComponentScan 自动扫描所有的 Spring 组件,包括 @Configuration 类.
@Import 注解可用于导入其他配置类@ExceptionHandler 拦截所有的异常信息
@Data Bean 里的 get set方法就可以不用写了,用的时候记得导入lombok
@Component 对应加载配置中的那些属性,将类交由Spring管控
@ConfigurationProperties 给对象进行属性注入
如果发现正在使用不需要的自动配置类,可以通过使用 @SpringBootApplication 的 exclude 属性来禁用它们
本地的是基于Idea 运行的,客户可以通过浏览器去访问自己的服务器 把Idea中的程序抽取出来 放到一个服务器上运行
mvn package 打包
java -jar jar包名 快速启动
打包过程:
双击执行package,打包到产品环境前,注意要跳过测试(Idea 里面有个按钮) 否则上到产品后有可能会有测试的数据。
有可能遇到的问题:
提示 没有主清单属性 原因是因为没有spring-boot-maven-plugin插件
提示 端口占用 netstat -ano 注意pid 是多 少
查找是哪个进程占用端口 tasklist | findstr “pid"
杀掉进程 task -q -pid "pid"
(1) 临时属性设置 :
如果遇到服务器上端口正在被占用,但是还不能停掉的情况可以启用临时端口命令:
java -jar jar包名 --server.port=8080(携带多个属性启动SpringBoot,属性间使用空格分隔)
如何利用IDEA为运维人员去测试临时属性是否生效:
启动的时候,在编辑里面 修改编辑配置中的程序实参设置属性 修改临时属性
但是一般情况下,不携带参数启动Spring程序:(为了安全性)
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication application = new SpringApplication(RuoYiApplication.class);
application.run(args);
}
当前配置文件 为开发人员所用 (优先级:低)
假设增加一个配置文件给项目经理用:找到配置文件所在目录 建立一个config目录 ,放配置文件(中)
假设还需要一个更高级别的配置文件,给客户用,那么可在打包的jar包的同层,建立配置文件 (高)
假设还需要一个最高级别的配置文件,那么可在打包的jar包同层,创建一个config目录,在该目录下面创建配置文件 (最高)
1.设置环境
2.应用环境
先写应用环境 再写设置环境
多环境开发(yml)
#应用环境
#公共配置
spring:
profiles:
active:dev
---
#设置环境
#生产环境
spring:
profiles:pro
server:
port:80
---
#开发环境
spring:
profiles:pro
server:
port:81
---
#测试环境
spring:
profiles:test
server:
port: 82
日志输出格式控制:
logging:
pattern:
console: "%d - %clr(%m) %n"
file:
name: server.log
logback:
rollingpolicy:
max-file-size:4KB
file-name-pattern:server.%d(yyyy-MM-dd).%i.log
%d:日期
%m: 消息
%n: 换行
%p:日志级别
%clr:颜色
%t:进程名
%c: 类名
通俗点讲就是 改完代码之后,服务器不需要重新启动会自动发生变化
中心思想 就是让服务器去感知到变化,然后自己去重启
1.开启开发者工具后启动热部署
2.使用构建项目操作启动热部署
3.热部署仅仅加载当前开发者自定义开发的资源,不加载jar资源
(1)开启开发者工具
在容器中添加新的设置 pom.xml :(记得加完以后,刷一下工程)
org.springframework.boot
spring-boot-devtools
true
(2)使用构建项目操作启动热部署 [ build Project 激活 或者快捷键(ctrl +F9) ]
那会有人问了,那我就直接重启项目岂不是更方便一些,这个热部署不也需要手动,干嘛要费劲还要配置依赖,这个时候我们就需要明白两个概念。
重启(Restart): 启动的包含 自定义开发代码,包含类,页面,配置文件等,加载位置restart类加载器
重载(Reload):启动的包含 jar包,加载位置base类加载器
如果我们重启项目,那就包含重启和重载两部分,而在实际开发中实际上是不需要重新去加载jar包的,jar只能说去换, 一般不会去改变,而热部署就只包含重启(Restart)的过程,它不包括重载(Reload),因此提高了效率。
这个时候就会有一些懒汉问了,那可不可以不用自己点,它自动build呢?答案是必然可以的,打开file->settings->Build->Compiler 中,勾选Build Project automatically
中文版IDEA如图
然后ctrl +alt+shift + / 打开Registry 勾选 complier automake.allow.when.app.running 即可,有的IDEA可能没有该选项,有可能是版本不同,新版的IDEA 在Settings中找到Advanced Settings中,勾选Allow auto-make to...
修改代码后,IDEA 失去焦点5s后 就会启动热部署。
注意:并不是所有东西修改后都会参与热部署,我们可以对热部署的加载范围进行配置:
# 服务模块
devtools:
restart:
# 热部署开关
enabled: true
exclude: static/**,public/** (配置不参与热部署的文件夹)
作用: 给对象进行属性注入
举例子:
application.yml:
servers:
ipAddress :192.168.0.1
port:2345
timeout:-1
java类:
@Component
@Data
@ConfigurationProperties(prefix = "servers")
public class ServiceConfig{
private String ipAddress;
private int port;
private long timeout;
}
main方法:
@SpringBootApplication
@EnableConfigurationProperties(ServerConfig.class)
public class DemoApplication {
public static void main(String[] args){
ConfigurableApplicationContext ctx = SpringApplication.run(Springboot13ConfigurationApplication.class,args);
ServerConfig bean = ctx.getBean(ServerConfig.class);
System.out.println(bean);
}
}
这样就可以拿到配置文件中的值了
打印结果为: ServerConfig(ipAddress=192.168.0.1,port=2345,timeout=-1)
@ConfigurationProperties 不仅可以为自己开发的组件绑定bean 还可以为第三方组件绑定bean,道理都是一样的这里不做演示。
@EnableConfigurationProperties 开启配置属性的功能 ,并设定目标是谁 ,管理就没有那么松散了。
注意:如果用了@EnableConfigurationProperties ,它所标注的类就不能用@Component
可能遇到的问题:
解决方法:添加如下代码:
org.springframework.boot
spring-boot-configuration-processor
无论配置中以哪一种形式定义,都可以取到其对应的值。
注意:宽松绑定不支持注解@Value 引用单个属性的方式
绑定前缀命名规范:仅能使用纯小写字母、数字、下划线作为合法字符
@Component
@Data
@ConfigurationProperties(prefix = "servers")
public class ServiceConfig{
private String ipAddress;
private int port;
private long timeout;
@DurationUnit(ChronoUnit.HOURS)
private Duration serverTimeOut;
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize dataSize;
}
(1)导入坐标
(2)开启对当前bean的属性注入校验@Validated
(3)使用具体校验规则规范数据校验格式
javax.validation
validation-api
org.hibernate.validator
hibernate-validator
类中使用:
@Component
@Data
//开启对当前bean的属性注入校验
@Validated
@ConfigurationProperties(prefix = "servers")
public class ServiceConfig{
private String ipAddress;
//设置具体的规则
@Max(value = 8888,message = "最大不能超过8888")
private int port;
private long timeout;
@DurationUnit(ChronoUnit.HOURS)
private Duration serverTimeOut;
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize dataSize;
}
方案一:
application.yml
test:
prop:testValue
java类:
@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
public class DemoTest {
@Test
@Value("${test.prop}")
private String msg;
void testProperties(){
System.out.println(msg);
}
}
方案二:properties属性可以为当前测试用例添加临时属性配置(可以再一个小范围内生效)
@SpringBootTest (properties = {"test.prop =testValue"}) //为测试用例添加临时属性
public class DemoTest {
@Test
@Value("${test.prop}")
private String msg;
void testProperties(){
System.out.println(msg);
}
}
方案三:args属性可以为当前测试用例添加临时的命令行参数
@SpringBootTest (args={"--test.prop=testValue"}) //为测试用例添加临时属性
public class DemoTest {
@Test
@Value("${test.prop}")
private String msg;
void testProperties(){
System.out.println(msg);
}
}
java类:
@Configuration
public class MsgConfig {
@Bean
public String msg(){
return "bean msg"
}
}
启动类:
@SpringBootTest
@Import({MsgConfig.class})
public class ConfigurationTest {
@Autowired
private String msg;
@Test
void testConfiguration(){
System.out.println(msg);
}
}
启动类:
@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ConfigurationTest {
@Test
void test(){
}
}
如果服务器上的端口被占用还可以采取随机端口
@SpringBootTest (webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)
controller:
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping
public String getById(){
System.out.println("getById is running...");
return "springboot";
}
}
虚拟调用:
匹配相应执行状态
@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
//开启虚拟调用
@AutoConfiguraMockMvc
public class WebTest{
@Test
void test(){
void testRandomPort(){
}
@Test
//注入虚拟MVC调用对象
void testWeb(@Autowired MockMvc mvc) throws Exception{
//创建了一个虚拟请求 当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books")
ResultAction action = mvc.perform(builder);
//1.设定预期值 与真实值进行比较 成功测试通过 失败测试失败
//定义本次调用的预期值
StatusResultMatchers status = MockMvcResultMatchers.status();
//预计本次调用时成功的:状态200
ResultMatcher ok = status.isOk();
//添加预计值到本次调用过程中进行匹配
action.andExpect(ok);
}
}
}
匹配响应体:(String)
@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
//开启虚拟调用
@AutoConfiguraMockMvc
public class WebTest{
@Test
void testBody(@Autowired MockMvc mvc) throws Exception{
//创建了一个虚拟请求 当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books")
ResultAction action = mvc.perform(builder);
//1.设定预期值 与真实值进行比较 成功测试通过 失败测试失败
//定义本次调用的预期值
ContentResultMatchers content= MockMvcResultMatchers.content();
ResultMatcher result = content.string("springboot");
//添加预计值到本次调用过程中进行匹配
action.andExpect(result);
}
}
}
匹配响应体:(json)
controller:
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping
public Book getById(){
System.out.println("getById is running...");
Book book = new Book();
book.setId(1);
book.setName("springboot");
book.setType("springboot");
return book;
}
}
@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
//开启虚拟调用
@AutoConfiguraMockMvc
public class WebTest{
@Test
void testJson(@Autowired MockMvc mvc) throws Exception{
//创建了一个虚拟请求 当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books")
ResultAction action = mvc.perform(builder);
//1.设定预期值 与真实值进行比较 成功测试通过 失败测试失败
//定义本次调用的预期值
ContentResultMatchers content= MockMvcResultMatchers.content();
ResultMatcher result = content.json("json串");
//添加预计值到本次调用过程中进行匹配
action.andExpect(result);
}
}
}
如果只想执行测试过程,测试后的结果数据不想存放又该如何处理?这就用到了事务的回滚。
业务层:
public interface BookService{
public boolean save(Book book);
}
实现类:
public class BookServiceImpl implements BookService{
@AutoWired
private BookDao bookDao;
@Override
public boolean save(Book book){
return bookDao.insert(book)>0;
}
}
测试类:
@SpringBootTest
@Transactional
//@Rollback(false) 可手动控制是否回滚 false就是不回滚
public class DaoTest{
@AutoWired
private BookService bookService;
@Test
void testSave(){
Book book = new Book();
book.setId(1);
book.setName("springboot");
book.setType("springboot");
bookService.save(book);
}
}
application.yml:
testcase:
book:
id: ${random.int}
name: ${random.value}
uuid:${random.uuid}
publishTime: ${random.long}
实体类:
@Component
@Data
@ConfigurationProperties(profix = "testcase.book")
public class BookCase {
private int id;
private String name;
private String uuid;
privete Long publishTime;
}
Springboot 提供的三种内嵌数据源对象
- HikariCP:默认内置数据源对象
- Tomcat 提供的DataSource:HikariCP不可用的情况下,且在web环境中,将使用tomcat服务器配置的数据源对象
- Commons DBCP:HikariCP不可用,tomcat数据源也不可用,将使用dbcp数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/xxx_db?serverTimezone=UTC
username: root
password: root
// mybatis-plus:
// global-config:
// dbConfig:
// idType: ASSIGN_ID
// 通用配置无法设置具体的数据源配置信息,仅提供基本的连接相关配置i,如需配置,在下一级配置中设置具体设定
hikari:
maximum-pool-size:50
内置持久化解决方案----jdbcTemplate
1.导入坐标
org.springframework.boot
spring-boot-starter-jdbc
2.使用:
@SpringBootTest
class SpringbootApplicationTest{
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
void testJdbc(){
String sql ="select * from book where id = 1";
List query = jdbcTemplate.query(sql,new RowMapper(){
@Override
public Book mapRow(ResultSet rs,int rowNum) throws SQLException {
Book temp = new Book();
temp.setId(rs.getInt("id"));
temp.setName(rs.getString("name"));
return temp;
}
});
System.out.println(query);
}
}
3.jdbcTemplate配置
spring:
jdbc:
template:
query-timeout: -1 //查询超时时间
max-rows: 500 //最大行数
fetch-size: -1 //缓存行数
1. Redis是什么?
Redis 是一款key-value存储结构的内存及NoSQL数据库。
2.特点
1.安装Redis
2.exe目录下 进入到cmd
3.输入启动命令 redis-server.exe redis.windows.conf(服务端启动命令)
redis -cli.exe 客户端启动命令
redis -cli 启动
set key value 存储值
get key 取值
set key value2 修改值
hset keya a1 aa1 哈希类型
hset keya a2 aa2
hget keya a1
"aa1"
hget keya a2
"aa2"
hget keya a3
(nil)
3.整合Springboot
(1) 创建Spring项目时勾选Redis选项
(2) 创建坐标,导入对应的jar包
org.springframework.boot
spring-boot-start-data-redis
(3) 做相应的配置 yml
spring:
redis:
# 地址
host: 172.16.234.121
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
# 密码(如没有密码请注释掉)
password: 1234
# 连接超时时间
timeout: 10s
# 是否开启ssl
ssl: false
(4) 使用
@SpringBootTest
public class SpringbootApplication {
@AutoWired
private RedisTemplate redisTemplate;
@Test
void set(){
ValueOperation ops = redisTemplate.opsForValue();
ops.set("age",18);
}
@Test
void get(){
ValueOperation ops = redisTemplate.opsForValue();
Object age = ops.get("age");
System.out.println(age);
}
//RedisTemplate 提供操作各种数据存储类型的接口API 如下举例为Hash类型
@Test
void set(){
ValueOperation ops = redisTemplate.opsForHash();
ops.put("info","a","aa"); //第一个值为key 第二个值为hashKey 第三个值是value
}
@Test
void get(){
HashOperation ops = redisTemplate.opsForHash();
Object val= ops.get("info","a");
System.out.println(val);
}
}
这里有个问题就是在客户端的存的数据,和springboot这里设置的key-value值不能同步,根本原因是客户端所操作的数据是string类型,所以上面的redisTemplate就需要变一变了,不然在客户端是不能根据key查到springboot中设置的值的。按照如下方式修改:
@SpringBootTest
public class SpringbootApplication {
@AutoWired
private StringRedisTemplate stringRedisTemplate;
//去拿客户端设置的值
@Test
void get(){
ValueOperation ops = stringRedisTemplate.opsForValue();
String age = ops.get("age");
System.out.println(age);
}
}
总结:客户端 RedisTemplate 以对象作为key和value,内部对数据进行序列化
解决方法: StringRedisTemplate 以字符串作为key和value,与redis客户端操作等效
jedis技术
使用步骤
(1)导入包
redis.clients
jedis
(2)配置:
spring:
redis:
host: localhost
port: 6379
client-type: jedis //默认lettuce
jedis:
pool:
max-active: 16
官网链接
http://docs.jcohy.com/docs/spring-boot/2.6.11/html5/zh-cn/features.html#features
未完不定期更新中.........