当前位置: 首页 > news >正文

【实战教程】SpringBoot全面指南:快速上手到项目实战(SpringBoot)

文章目录

  • 【实战教程】SpringBoot全面指南:快速上手到项目实战(SpringBoot)
    • 1. SpringBoot介绍
      • 1.1 SpringBoot简介
      • 1.2系统要求
      • 1.3 SpringBoot和SpringMVC区别
      • 1.4 SpringBoot和SpringCloud区别
    • 2.快速入门
    • 3. Web开发
      • 3.1 静态资源访问
      • 3.2 渲染Web页面
      • 3.3 YML与Properties用法
      • 3.4使用Freemarker模板引擎渲染web视图
      • 3.5 使用thymeleaf渲染Web页面
    • 4.数据库访问
      • 4.1 springboot整合使用JdbcTemplate
      • 4.2 springboot整合使用mybatis
      • 4.3 springboot整合多数据源
    • 5.事务管理
      • 5.1 Springboot整合事务管理
      • 5.2 SpringBoot分布式事务管理
    • 6.整合热部署
      • 6.1 Spring Boot集成lombok让代码更简洁
      • 6.2 Spring Boot整合热部署框架
    • 7.整合配置文件
      • 7.1使用@value注解和@ConfigurationProperties注解
      • 7.2配置文件占位符
      • 7.3多环境配置和核心配置
    • 8.日志管理
      • 8.1使用logback记录日志
      • 8.2使用log4j记录日志
      • 8.3使用AOP统一处理Web请求日志
    • 9.其他内容
      • 9.1使用@Scheduled创建定时任务
      • 9.2使用@Async实现异步调用
      • 9.3全局捕获异常
      • 9.4发布打包


【实战教程】SpringBoot全面指南:快速上手到项目实战(SpringBoot)

1. SpringBoot介绍

1.1 SpringBoot简介

SpringBoot 是一个快速开发的框架, 封装了Maven常用依赖、能够快速的整合第三方框架;简化XML配置,全部采用注解形式,内置Tomcat、Jetty、Undertow,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringBoot原理介绍:

  1. 能够帮助开发者实现快速整合第三方框架 (原理:Maven依赖封装)
  2. 去除xml配置 完全采用注解化 (原理:Spring体系中内置注解方式)
  3. 无需外部Tomcat、内部实现服务器(原理:Java语言支持内嵌入Tomcat服务器)

1.2系统要求

Java1.8及以上
Spring Framework 5.0及以上
本课程采用Java1.8版本、SpringBoot2.1.8版本

1.3 SpringBoot和SpringMVC区别

SpringBoot 是一个快速开发的框架,能够快速的整合第三方框架,简化XML配置,全部采用注解形式,内置Tomcat容器,帮助开发者能够实现快速开发,SpringBoot的Web组件默认集成的是SpringMVC框架。
SpringMVC是控制层。

1.4 SpringBoot和SpringCloud区别

SpringBoot 是一个快速开发的框架,能够快速的整合第三方框架,简化XML配置,全部采用注解形式,内置Tomcat容器,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringMVC是控制层。
SpringCloud依赖与SpringBoot组件,使用SpringMVC编写Http协议接口,同时SpringCloud是一套完整的微服务解决框架。


2.快速入门

2.1创建一个Maven工程
在这里插入图片描述

2.2 pom文件引入依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version>
</parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

spring-boot-starter-parent作用
在pom.xml中引入spring-boot-start-parent,spring官方的解释叫什么stater poms,它可以提供dependency management,也就是说依赖管理,引入以后在申明其它dependency的时候就不需要version了,后面可以看到。
spring-boot-starter-web作用
springweb 核心组件

2.3 @RestController
@RestController 是由 @Controller(控制层注解)+@ResponBody(数据传输格式为 json 格式)组合而成的
Rest 微服务接口开发中 rest 风格的数据传输格式为 json 格式,采用HTTP协议
在上加上RestController 表示修饰该Controller所有的方法返回JSON格式,直接可以编写
Restful接口
注意该注解是(@RestController )SpringMVC提供的哦!

2.4@EnableAutoConfiguration
该注解:作用在于让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置
这个注解告诉Spring Boot根据添加的jar依赖猜测你想如何配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,所以auto-configuration将假定你正在开发一个web应用并相应地对Spring进行设置。

2.5 SpringBoot的3种启动方式
方式一

package com.zhaoli.service;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@EnableAutoConfiguration
public class HelloworldService {@RequestMapping("/hello")public String hello() {return "Hello World!";}public static void main(String[] args) {SpringApplication.run(HelloworldService.class, args);}
}

可以请求本类中的 url
启动主程序,打开浏览器访问http://127.0.0.1:8080/hello,可以看到页面输出Hello World
在这里插入图片描述

方式二

package com.zhaoli.service;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;@ComponentScan("com.zhaoli.service")//扫包范围
@EnableAutoConfiguration
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}
package com.zhaoli.service;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HellowordService {@RequestMapping("/hello02")public String hello02() {return "Hello 赵立";}
}

可以启动扫包范围下的所有类中的 url

方式三(推荐使用)
在启动类上直接加上@SpringBootApplication即可
@SpringBootApplication@Configuration@EnableAutoConfiguration@ComponentScan 注解所修饰,换言之 Springboot 提供了统一的注解来替代以上三个注解
扫包范围:在启动类上加上@SpringBootApplication注解,当前包下或者子包下所有的类都可以扫到。

package com.zhaoli.service;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}

3. Web开发

3.1 静态资源访问

在我们开发Web应用的时候,需要引用大量的jscss、图片等静态资源。
默认配置
Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:

/static
/public
/resources	
/META-INF/resources

举例:我们可以在src/main/resources/目录下创建static,在该位置放置一个图片文件。启动程序后,尝试访问http://localhost:8080/one.png。如能显示图片,配置成功。

微服务项目
前后端分离
前端----vue----前端工程师
后端—springboot–后端工程师

动静分离 部署cdn上
cdn 减少带宽距离传输 减少自己服务器带宽;

3.2 渲染Web页面

com.zhaoli.controller—视图层 渲染我们页面
com.zhaoli.service—业务逻辑层
com.zhaoli.dao—数据库访问层

渲染Web页面
在之前的示例中,我们都是通过@RestController来处理请求,所以返回的内容为json对象。那么如果需要渲染html页面的时候,要如何实现呢?
模板引擎 能够非常好的帮助seo搜索到该网页
在动态HTML实现上Spring Boot依然可以完美胜任,并且提供了多种模板引擎的默认配置支持,所以在推荐的模板引擎下,我们可以很快的上手开发动态网站。
Spring Boot提供了默认配置的模板引擎主要有以下几种:

  1. Thymeleaf
  2. FreeMarker
  3. Velocity
  4. Groovy
  5. Mustache
    Spring Boot建议使用这些模板引擎,避免使用JSP,若一定要使用JSP将无法实现Spring Boot的多种特性,具体可见后文:支持JSP的配置
    当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates。当然也可以修改这个路径,具体如何修改,可在后续各模板引擎的配置属性中查询并修改。

3.3 YML与Properties用法

SpringBoot支持两种配置方式,一种是properties文件,一种是yml。(都是在resources目录下)
使用yml可以减少配置文件的重复性。
例如:application.properties配置

test.name=zhaoli
test.age=21

例如:application.yml配置

test:name: zhaoliage: 20

在企业中application.yml方式用的是比较多的;

package com.zhaoli.service;import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class MayiktPropertiesService {@Value("${mayikt.name}")private String name;@Value("${mayikt.age}")private String age;@RequestMapping("/getProperties")public String getProperties(){return name+"---------"+age;}
}

3.4使用Freemarker模板引擎渲染web视图

1.Maven依赖

<!-- 引入freeMarker的依赖包. -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2.后端代码

package com.zhaoli.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.Map;@Controller
public class FreemarkerIndexController {@RequestMapping("/freemarkerIndex")public String freemarkerIndex(Map<String,String> result){//转发到页面展示数据result.put("name","赵立");return "freemarkerIndex";}
}

3.前端代码

src/main/resources/创建一个templates文件夹,用来存 *.ftl

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"/><title></title>
</head>
<body>
${name}
</body>
</html>

4.Freemarker其他用法
Freemarker配置
新建application.yml文件 (加粗提示对应的配置可以进行修改)

spring:
##Freemarker配置http:encoding:force: true### 模版引擎编码为UTF-8charset: UTF-8freemarker:allow-request-override: falsecache: falsecheck-template-location: truecharset: UTF-8content-type: text/html; charset=utf-8expose-request-attributes: falseexpose-session-attributes: falseexpose-spring-macro-helpers: false## 模版文件结尾.ftlsuffix: .ftl## 模版文件目录template-loader-path: classpath:/templates

*.ftl 文件中使用符号替换方法

符号替换为(条件判断)
>gt 或者 <#if(x>y)>
>=gte 或者 <#if(x>=y)>
<lt 或者 <#if(x<y)>
<=lte 或者 <#if(x<=y)>

判断条件用法
com.zhaoli.controller.FreemarkerIndexController

@RequestMapping("/freemarkerIndex02")
public String freemarkerIndex02(Map<String, Object> result) {//转发到页面展示数据result.put("name", "赵立");//0为男 1为女result.put("sex", "0");result.put("age", 21);return "freemarkerIndex02";
}

freemarkerIndex02.ftl

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"/><title></title>
</head>
<body>
${name}
<#if sex=='0'>男
<#elseif sex='1'><#else >其他
</#if>
<#if age gt 17>已经成年了
<#else >没成年
</#if>
</body>
</html>

在这里插入图片描述

list集合
com.zhaoli.controller.FreemarkerIndexController

@RequestMapping("/freemarkerIndex03")
public String freemarkerIndex03(Map<String, Object> result) {//转发到页面展示数据List<String> userLists = new ArrayList<>();userLists.add("zl");userLists.add("fj");userLists.add("lfc");userLists.add("ywq");result.put("userList",userLists);return "freemarkerIndex03";

freemarkerIndex03.ftl

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"/><title></title>
</head>
<body>
<#list userList as user>${user}
</#list>
</body>
</html>

3.5 使用thymeleaf渲染Web页面

1 .什么是thymeleaf
thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎,类似JSPVelocityFreeMaker等,它也可以轻易的与Spring MVCWeb框架进行集成作为Web应用的模板引擎。

2.Maven依赖

<!--引入thymeleaf的依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

3.配置文件新增
新建application.yml文件

###ThymeLeaf配置
spring:thymeleaf:#prefix:指定模板所在的目录prefix: classpath:/templates/#check-tempate-location: 检查模板路径是否存在check-template-location: true#cache: 是否缓存,开发模式下设置为false,避免改了模板还要重启服务器,线上设置为true,可以提高性能。cache: truesuffix:  .htmlencoding: UTF-8mode: HTML5

4.案例代码
com.zhaoli.entity.UserEntity

package com.zhaoli.entity;public class UserEntity {private String userName;
private Integer age;
}

com.zhaoli.controller.ThymeleafController

package com.zhaoli.controller;import com.zhaoli.entity.UserEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.Map;@Controller
public class ThymeleafController {@RequestMapping("/thymeleaf")public String thymeleaf(Map<String, Object> result) {result.put("user", new UserEntity("赵立", 20));return "thymeleaf";}
}

src/main/resources/创建一个templates文件夹,用来存 *html

<!DOCTYPE html>
<!--需要在HTML文件中加入以下语句: -->
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Show User</title></head><body><table>姓名:<span th:text="${user.userName}"></span>年龄:<span th:text="${user.age}"></span></table></body>
</html>

5.高级写法
循环语句:
com.zhaoli.entity.UserEntity 同上
com.zhaoli.controller.ThymeleafController

@RequestMapping("/thymeleaf02")public String thymeleaf02(Map<String, Object> result) {List<UserEntity> userLists = new ArrayList<>();userLists.add(new UserEntity("赵立", 21));userLists.add(new UserEntity("fj", 20));result.put("userList", userLists);return "thymeleaf02";
}

thymeleaf02.html

<!DOCTYPE html>
<!--需要在HTML文件中加入以下语句: -->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Show User</title>
</head>
<body>
<table><ul th:each="user:${userList}"><li th:text="${user.userName}"></li><li th:text="${user.age}"></li></ul>
</table>
</body>
</html>

If判断:

<span th:if="${user.age>17}">已经成年啦</span>
<span th:if="${user.age<17}">未成年</span>

详细可以更多语法可以查看https://www.thymeleaf.org/documentation.html


4.数据库访问

4.1 springboot整合使用JdbcTemplate

1.pom文件引入

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version>
</parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 引入freeMarker的依赖包. --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!--引入thymeleaf的依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- SpringBoot 整合 jdbc 模板框架--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- SpringBoot 整合 mysql 驱动类 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.21</version></dependency>
</dependencies>

2.application.yml新增配置

  ##springboot整合使用JdbcTemplatedatasource:url: jdbc:mysql://localhost:3306/mayikt_springboot?serverTimezone=UTC&useSSL=falseusername: rootpassword: 20020806driver-class-name: com.mysql.jdbc.Driver

3.数据库表结构

CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) NOT NULL COMMENT '用户名称',`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

4.案例代码
com.zhaoli.entity.UserEntity

public class MayiktUserEntity {private Integer id;private String userName;
private Integer age;
}

com.zhaoli.service.UserService

package com.zhaoli.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserService {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 插入数据到 users 表*/@RequestMapping("/inserUser")public String inserUser(String userName, Integer age) {int update = jdbcTemplate.update("INSERT INTO users VALUES(null,?,?);", userName, age);return update > 0 ? "success" : "fail";}
}

com.zhaoli.App App类

package com.zhaoli;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}

4.2 springboot整合使用mybatis

1.pom文件引入

<!-- springboot 整合mybatis -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.1.1</version>
</dependency>

2.application.yml 新增配置

  ##springboot整合使用mybatisdatasource:url: jdbc:mysql://localhost:3306/mayikt_springboot?serverTimezone=UTC&useSSL=falseusername: rootpassword: 20020806driver-class-name: com.mysql.jdbc.Driver

3.案例代码
数据库表结构同上
com.zhaoli.entity.UserEntity 同上
com.zhaoli.mapper.UserMapper 接口

package com.zhaoli.mapper;import com.zhaoli.entity.MayiktUserEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;public interface UserMapper {@Insert("INSERT INTO users VALUES(null,#{userName},#{age});")int insertUser(@Param("userName") String userName, @Param("age")Integer age);@Select("SELECT id,name AS userName,age FROM users WHERE id=#{id};")MayiktUserEntity selectByUserId(@Param("id")Integer id);
}

com.zhaoli.service.UserService

package com.zhaoli.service;import com.zhaoli.entity.MayiktUserEntity;
import com.zhaoli.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserService {@Autowiredprivate UserMapper userMapper;/*** mybatis 查询*/@RequestMapping("/mybatisfinbyId")public MayiktUserEntity mybatisfinbyId(Integer id){return userMapper.selectByUserId(id);}/*** mybatis 插入*/@RequestMapping("/mybatisInser")public String mybatisInser(String userName, Integer age) {int inser = userMapper.insertUser(userName, age);return inser > 0 ? "success" : "fail";}
}

com.zhaoli.App App类

package com.zhaoli;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.zhaoli.mapper")//将 mapper 包下的类、接口注入到ioc 容器中
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}

在这里插入图片描述
在这里插入图片描述

4.3 springboot整合多数据源

1.Maven相关依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version>
</parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- springboot 整合mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.1.1</version></dependency><!-- SpringBoot 整合 mysql 驱动类 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency>
</dependencies>

2.数据库表结构

CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) NOT NULL COMMENT '用户名称',`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `order_number` (`id` int(11) NOT NULL AUTO_INCREMENT,`order_name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

3.配置文件中新增两个数据源

resources.application.yml
spring:datasource:###会员数据库member:jdbc-url: jdbc:mysql://localhost:3306/user?serverTimezone=UTC&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driver###订单数据库order:jdbc-url: jdbc:mysql://localhost:3306/order?serverTimezone=UTC&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driver

备注:如果是SpringBoot2配置多数据源 ,报如下错误:
jdbcUrl is required with driverClassName.或者Cause: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.] with root cause
解决方案:
spring.datasource.urlspring.datasource.driverClassName,换成
spring.datasource.jdbc-urlspring.datasource.driver-class-name

4.数据库数据源相关配置
会员数据源

@Configuration
@MapperScan(basePackages = "com.zhaoli.member.mapper", sqlSessionFactoryRef = "memberSqlSessionFactory")
public class MemberDataSourceConfig {/*** 将会员db注册到容器中** @return*/@Bean(name = "memberDataSource")@ConfigurationProperties(prefix = "spring.datasource.member")public DataSource memberDataSource() {return DataSourceBuilder.create().build();}/*** 将会员SqlSessionFactory注册到容器中** @param dataSource* @return* @throws Exception*/@Bean(name = "memberSqlSessionFactory")public SqlSessionFactory memberSqlSessionFactory(@Qualifier("memberDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(memberDataSource());return sqlSessionFactoryBean.getObject();}/*** 创建会员管理器** @param dataSource* @return*/@Bean(name = "memberTransactionManager")public DataSourceTransactionManager memberTransactionManager(@Qualifier("memberDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}/*** 创建订单sqlSesion模版** @param sqlSessionFactory* @return* @throws Exception*/@Bean(name = "memberSqlSessionTemplate")public SqlSessionTemplate menberSqlSessionTemplate(@Qualifier("memberSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}
}

订单数据源

@Configuration
@MapperScan(basePackages = "com.zhaoli.order.mapper", sqlSessionFactoryRef = "orderSqlSessionFactory")
public class OrderDataSourceConfig {/*** 将订单db注册到容器中** @return*/@Bean(name = "orderDataSource")@ConfigurationProperties(prefix = "spring.datasource.order")public DataSource orderDataSource() {return DataSourceBuilder.create().build();}/*** 将订单SqlSessionFactory注册到容器中** @param dataSource* @return* @throws Exception*/@Bean(name = "orderSqlSessionFactory")public SqlSessionFactory orderSqlSessionFactory(@Qualifier("orderDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(orderDataSource());return sqlSessionFactoryBean.getObject();}/*** 创建订单管理器** @param dataSource* @return*/@Bean(name = "orderTransactionManager")public DataSourceTransactionManager orderTransactionManager(@Qualifier("orderDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}/*** 创建订单sqlSesion模版** @param sqlSessionFactory* @return* @throws Exception*/@Bean(name = "orderSqlSessionTemplate")public SqlSessionTemplate menberSqlSessionTemplate(@Qualifier("orderSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}
}

5.创建分包Mapper
会员mapper

public interface MemberMapper {@Insert("insert into users values(null,#{name},#{age});")public int addUser(@Param("name") String name, @Param("age") Integer age);
}

订单mapper

public interface OrderMapper {@Insert("insert into order_number values(null,#{number});")int inserOrder(@Param("number") String number);
}

6.启动项目

@SpringBootApplication
public class App{public static void main(String[] args) {SpringApplication.run(App.class);}
}

5.事务管理

5.1 Springboot整合事务管理

springboot默认集成事务,只主要在方法上加上@Transactional即可

5.2 SpringBoot分布式事务管理

使用springboot+jta+atomikos 分布式事物Transactional管理

1.多数据源分布式事务案例

@Service
public class MemberService {@Autowiredprivate MemberMapper memberMapper;@Autowiredprivate OrderMapper orderMapper;@Transactional(transactionManager = "memberTransactionManager")public int addUser(String userName, Integer age) {int result = memberMapper.addUser(userName, age);orderMapper.inserOrder(userName);int j = 1 / age;return result;}
}

2.Maven相关依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

3.新增配置文件信息

spring:datasource:###会员数据库member:url: jdbc:mysql://localhost:3306/user?serverTimezone=UTC&useSSL=falseusername: rootpassword: rootborrowConnectionTimeout: 30loginTimeout: 30maintenanceInterval: 60maxIdleTime: 60maxLifetime: 20000maxPoolSize: 25minPoolSize: 3uniqueResourceName: orderDatasource###订单数据库order:url: jdbc:mysql://localhost:3306/order?serverTimezone=UTC&useSSL=falseusername: rootpassword: rootborrowConnectionTimeout: 30loginTimeout: 30maintenanceInterval: 60maxIdleTime: 60maxLifetime: 20000maxPoolSize: 25minPoolSize: 3uniqueResourceName: memberDatasource

4.读取配置文件信息

@ConfigurationProperties(prefix = "spring.datasource.member")
@Data
public class MemberConfig {private String url;private String userName;private String passWord;private int minPoolSize;private int maxPoolSize;private int maxLifetime;private int borrowConnectionTimeout;private int loginTimeout;private int maintenanceInterval;private int maxIdleTime;private String testQuery;private String uniqueResourceName;
}
@ConfigurationProperties(prefix = "spring.datasource.order")
@Data
public class OrderConfig {private String url;private String userName;private String passWord;private int minPoolSize;private int maxPoolSize;private int maxLifetime;private int borrowConnectionTimeout;private int loginTimeout;private int maintenanceInterval;private int maxIdleTime;private String testQuery;private String uniqueResourceName;
}

5.创建多数据源

@Configuration
@MapperScan(basePackages = "com.zhaoli.member.mapper", sqlSessionTemplateRef = "memberSqlSessionTemplate")
public class MemberDataSourceConfig {//@Configuration xml  MemberDataSourceConfig.xml/*** 创建我们的DataSource*/@Bean("memberDataSource")public DataSource memberDataSource(MemberConfig memberConfig) throws SQLException {// 1.创建MysqlXADataSourceMysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();mysqlXaDataSource.setUrl(memberConfig.getUrl());mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);mysqlXaDataSource.setPassword(memberConfig.getPassWord());mysqlXaDataSource.setUser(memberConfig.getUserName());mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);// 2.将本地事务注册到创 Atomikos全局事务AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();xaDataSource.setXaDataSource(mysqlXaDataSource);xaDataSource.setUniqueResourceName(memberConfig.getUniqueResourceName());xaDataSource.setMinPoolSize(memberConfig.getMinPoolSize());xaDataSource.setMaxPoolSize(memberConfig.getMaxPoolSize());xaDataSource.setMaxLifetime(memberConfig.getMaxLifetime());xaDataSource.setBorrowConnectionTimeout(memberConfig.getBorrowConnectionTimeout());xaDataSource.setLoginTimeout(memberConfig.getLoginTimeout());xaDataSource.setMaintenanceInterval(memberConfig.getMaintenanceInterval());xaDataSource.setMaxIdleTime(memberConfig.getMaxIdleTime());xaDataSource.setTestQuery(memberConfig.getTestQuery());return xaDataSource;}/*** 创建我们的SqlSessionFactory*/@Bean(name = "memberSqlSessionFactory")public SqlSessionFactory memberSqlSessionFactory(@Qualifier("memberDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);return sqlSessionFactoryBean.getObject();}/*** 创建订单sqlSesion模版*/@Bean(name = "memberSqlSessionTemplate")public SqlSessionTemplate memberSqlSessionTemplate(@Qualifier("memberSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}
}
@Configuration
@MapperScan(basePackages = "com.zhaoli.order.mapper", sqlSessionTemplateRef = "orderSqlSessionTemplate")
public class OrderDataSourceConfig {//@Configuration xml  orderDataSourceConfig.xml/*** 创建我们的DataSource*/@Bean("orderDataSource")public DataSource orderDataSource(OrderConfig orderConfig) throws SQLException {// 1.创建MysqlXADataSourceMysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();mysqlXaDataSource.setUrl(orderConfig.getUrl());mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);mysqlXaDataSource.setPassword(orderConfig.getPassWord());mysqlXaDataSource.setUser(orderConfig.getUserName());mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);// 2.将本地事务注册到创 Atomikos全局事务AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();xaDataSource.setXaDataSource(mysqlXaDataSource);xaDataSource.setUniqueResourceName(orderConfig.getUniqueResourceName());xaDataSource.setMinPoolSize(orderConfig.getMinPoolSize());xaDataSource.setMaxPoolSize(orderConfig.getMaxPoolSize());xaDataSource.setMaxLifetime(orderConfig.getMaxLifetime());xaDataSource.setBorrowConnectionTimeout(orderConfig.getBorrowConnectionTimeout());xaDataSource.setLoginTimeout(orderConfig.getLoginTimeout());xaDataSource.setMaintenanceInterval(orderConfig.getMaintenanceInterval());xaDataSource.setMaxIdleTime(orderConfig.getMaxIdleTime());xaDataSource.setTestQuery(orderConfig.getTestQuery());return xaDataSource;}/*** 创建我们的SqlSessionFactory*/@Bean(name = "orderSqlSessionFactory")public SqlSessionFactory orderSqlSessionFactory(@Qualifier("orderDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);return sqlSessionFactoryBean.getObject();}
//
//    /**
//     * 创建会员管理器
//     */
//    @Bean(name = "orderTransactionManager")
//    public DataSourceTransactionManager orderTransactionManager(@Qualifier("orderDataSource") DataSource dataSource) {
//        return new DataSourceTransactionManager(dataSource);
//    }/*** 创建订单sqlSesion模版*/@Bean(name = "orderSqlSessionTemplate")public SqlSessionTemplate orderSqlSessionTemplate(@Qualifier("orderSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}
}

如果多数据源使用事务报错的话
cted single matching bean but found 2: memberTransactionManager,orderTransactionManager
@Transactional(transactionManager = "memberTransactionManager")
明确指定使用那个事务管理器即可

6.启动加载配置
@EnableConfigurationProperties({OrderConfig.class, MemberConfig.class})


6.整合热部署

6.1 Spring Boot集成lombok让代码更简洁

1.需要安装Idea整合 整合Lombok插件
在这里插入图片描述

2.搜索Lombok插件即可
在这里插入图片描述

3.点击install然后,安装成功之后,点击 重启idea 即可。

整合lombok注意事项

  1. 需要在idea中安装lombok插件;-----没有做
  2. 引入到lombok依赖;
    加上了注解,根本就没有生成get和set方法。

原理:
实际上在开发写代码的时候 是不需要写get和set方法,但是在编译class文件中,帮你自动生成好这样get和set方法 放入到class文件中。

4.添加lombok依赖

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>

5.打印日志
//App 是类的名称,在那个类中用就写那个类
private static Logger log = Logger.getLogger(App.class);
直接在类上加上@Slf4j 就不用写上面这行代码

6.其他特性

注解描述
@Data自动生成getter/setter方法,toString()方法,equals()方法,hashCode()方法,不带参数的构造方法。
@NonNull避免NullPointerException,确保非空对象引用。
@CleanUp自动管理需要关闭的资源,无需手动在finally块中调用close()方法。
@Setter自动生成setter方法。
@Getter自动生成getter方法。
@ToString自动生成toString()方法。
@EqualsAndHashCode从对象的字段生成hashCode()equals()方法的实现。
@NoArgsConstructor自动生成无参构造方法。
@RequiredArgsConstructor根据final或@NotNull修饰的属性自动生成构造方法。
@AllArgsConstructor自动生成包含所有属性的构造方法。
@Value用于注解不可变的final类。
@Builder自动生成复杂对象的构造器API。
@SneakyThrows捕获并隐藏检查型异常,需谨慎使用。
@Synchronized将方法或代码块标记为同步的,保证线程安全。
@Getter(lazy=true)延迟加载属性值,仅适用于Java 8及以上版本。
@Log支持不同的日志框架,例如使用@Log4j注解引入Log4j日志对象。

6.2 Spring Boot整合热部署框架

1.什么是热部署
修改java类或页面或者静态文件,不需要手动重启
原理:类加载器
适合于本地开发环境

2. Maven依赖

<!--SpringBoot热部署配置 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional>
</dependency>

3. Idea工具设置

  1. `“File” -> “Settings” -> “Build,Execution,Deplyment” -> “Compiler”,选中打勾 “Build project automatically”
    在这里插入图片描述

  2. 组合键:“Shift+Ctrl+Alt+/” ,选择 “Registry” ,选中打勾 “compiler.automake.allow.when.app.running”
    在这里插入图片描述

新版本的IDEA在这里设置
在这里插入图片描述

4.效果演示
按住保存键,自动帮我实现重启项目


7.整合配置文件

1. 在springboot整合配置文件,分成两大类
application.properties
application.yml
或者是
Bootstrap.properties
Bootstrap.yml
相对于来说yml文件格式写法更加精简,减少配置文件的冗余性。

2. 加载顺序:
bootstrap.yml 先加载 application.yml后加载
bootstrap.yml 用于应用程序上下文的引导阶段。
bootstrap.yml 由父Spring ApplicationContext加载。
3.区别:
bootstrap.ymlapplication.yml 都可以用来配置参数。
bootstrap.yml 用来程序引导时执行,应用于更加早期配置信息读取。可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。一旦bootStrap.yml 被加载,则内容不会被覆盖。
application.yml 可以用来定义应用级别的, 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
分布式配置中心:

Properties在线转换yml格式网址:https://www.toyaml.com/index.html

7.1使用@value注解和@ConfigurationProperties注解

@value注解

@Value("${test.name}")//可以获取到配置文件中对应的值
private String name; 

@ConfigurationProperties注解
Maven依赖

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>

com.zhaoli.entity

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "test")
public class TestUserEntity {private String addres;private String age;private String name;//省略了get set toString
}

配置文件

test:addres: www.zhaoli.comage: 22name: test

com.zhaoli.service

@Autowired
private TestUserEntity userEntity;@RequestMapping("/getNameAndAgeAddres")
public String getNameAndAgeAddres() {return userEntity.toString();
}

7.2配置文件占位符

SpringBoot的配置文件中,我们可以使用SpringBoot提供的的一些随机数
${random.value}${random.int}${random.long}
${random.int(10)}表示获取10以内的随机数、${random.int[1024,65536]}
-${app.name:默认值} 来制定找不到属性时的默认值

7.3多环境配置和核心配置

resources.templates.application.yml 里面指定读取文件的名称

spring:profiles:active: (dev或者test或者prd)

application-dev.yml:开发环境
application-test.yml:测试环境
application-prd.yml:生产环境

核心配置

server:
## 设定端口号port: 8081servlet:
## 设置 springboot 项目访问路径context-path: /mayikt
Springboot 默认的情况下整合tomcat容器

8.日志管理

8.1使用logback记录日志

Springboot 已经默认帮你整合好了logback
日志输出文件在当前项目路径log文件夹下
1.Maven依赖

<!-- 添加lombok依赖 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>

2.在resources包下新建一个log包,在包下建 logback.xml 在里面进行配置(拷贝到里面即可)

<configuration><!--本文主要输出日志为控制台日志,系统日志,sql日志,异常日志--><!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,,,, --><!--控制台--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d %p (%file:%line\)- %m%n</pattern><charset>UTF-8</charset></encoder></appender><!--系统info级别日志--><!--<File> 日志目录,没有会自动创建--><!--<rollingPolicy>日志策略,每天简历一个日志文件,或者当天日志文件超过64MB时--><!--encoder 日志编码及输出格式--><appender name="fileLog"class="ch.qos.logback.core.rolling.RollingFileAppender"><File>log/file/fileLog.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/file/fileLog.log.%d.%i</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- or whenever the file size reaches 64 MB --><maxFileSize>64 MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><encoder><pattern>%d %p (%file:%line\)- %m%n</pattern><charset>UTF-8</charset><!-- 此处设置字符集 --></encoder></appender><!--sql日志--><appender name="sqlFile"class="ch.qos.logback.core.rolling.RollingFileAppender"><File>log/sql/sqlFile.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/sql/sqlFile.log.%d.%i</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- or whenever the file size reaches 64 MB --><maxFileSize>64 MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><!--对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。--><encoder><!--用来设置日志的输入格式--><pattern>%d %p (%file:%line\)- %m%n</pattern><charset>UTF-8</charset><!-- 此处设置字符集 --></encoder></appender><!--异常日志--><appender name="errorFile"class="ch.qos.logback.core.rolling.RollingFileAppender"><File>log/error/errorFile.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/error/errorFile.%d.log.%i</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- or whenever the file size reaches 64 MB --><maxFileSize>64 MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><!--对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。--><encoder><!--用来设置日志的输入格式--><pattern>%d %p (%file:%line\)- %m%n</pattern><charset>UTF-8</charset><!-- 此处设置字符集 --></encoder><!--日志都在这里 过滤出 error使用 try {}catch (Exception e){} 的话异常无法写入日志,可以在catch里用logger.error()方法手动写入日志--><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--  日志输出级别 --><!--All\DEBUG\INFO\WARN\ERROR\FATAL\OFF--><!--打印info级别日志,分别在控制台,fileLog,errorFile输出异常日志在上面由过滤器过滤出ERROR日志打印--><root level="INFO"><appender-ref ref="fileLog" /><appender-ref ref="console" /><appender-ref ref="errorFile" /></root><!--打印sql至sqlFile文件日志--><logger name="com.dolphin.mapper" level="DEBUG" additivity="false"><appender-ref ref="console" /><appender-ref ref="sqlFile" /></logger>
</configuration>

3.在 resources 目录下的 application.yml 文件内新增 application 配置

###指定读取logback配置文件
logging:config: classpath:log/logback.xml

4.测试案例

@RestController
@Slf4j
public class MyIndexService {/*** 演示打印日志*/@RequestMapping("/getNameAndAge")public String getNameAndAge(String name,Integer age){log.info("name:{},age:{}",name,age);return name+","+age;}
}

在这里插入图片描述

5.日志级别
ALL 最低等级的,用于打开所有日志记录。
TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。
DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示
ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
OFF 最高等级的,用于关闭所有日志记录。

6.日志目录
在这里插入图片描述

8.2使用log4j记录日志

日志级别描述输出源格式
TRACE追踪,程序每推进一步可以写入一个TRACE级别的日志,通常用于非常详细的执行流程跟踪。CONSOLESimpleLayout
DEBUG调试,用于记录调试信息,通常是最低级别,帮助开发者理解程序运行情况。FILEHTMLLayout
INFO重要信息,用于记录应用程序运行的关键信息,是使用较为频繁的日志级别。PatternLayout
WARN警告,记录可能需要注意的信息,这些信息虽然不是错误,但可能会导致问题或需要注意的情况。
ERROR错误,记录应用程序中的错误信息,这类信息表明应用程序中出现了问题。CONSOLE
FATAL致命错误,记录非常严重的错误信息,通常指应用程序无法继续运行下去的情况。FILE
机制:如果一条日志信息的级别大于等于配置文件的级别,则记录这条日志信息。
输出源:日志可以输出到控制台(CONSOLE)或文件(FILE)。
格式:日志输出的格式可以是简单的(SimpleLayout),HTML表格形式(HTMLLayout),或者自定义格式(PatternLayout)。

1.Maven依赖

<!-- spring boot start -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><!-- 排除自带的logback依赖 --><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions>
</dependency><!-- springboot-log4j -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j</artifactId><version>1.3.8.RELEASE</version>
</dependency>

<!-- spring boot start -->
这段代码是使用Maven构建项目时,添加spring-boot-starter依赖的一种方式,并且通过exclusions排除了其中的logback依赖。
当你使用类似的配置时,spring-boot-starter依赖会被添加到项目中,并且排除了 spring-boot-starter-logging。这样,你可以根据自己的需求选择适合的日志框架进行使用
这个排除logback依赖的操作可以用来替换其他的日志框架,或者使用自定义的日志框架进行日志的输出

2.新建log4j配置文件
resources 目录下新建文件log4j.properties
记得根据自己的项目修改里面的日志输出路径

#log4j.rootLogger=CONSOLE,info,error,DEBUG
log4j.rootLogger=DEBUG,error,CONSOLE,info
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender     
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout     
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n    log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.layout=org.apache.log4j.PatternLayout     
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  
log4j.appender.info.datePattern='.'yyyy-MM-dd
log4j.appender.info.Threshold = info   
log4j.appender.info.append=true
log4j.appender.info.File=E:/code/log/info.loglog4j.logger.error=error  
log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.layout=org.apache.log4j.PatternLayout     
log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  
log4j.appender.error.datePattern='.'yyyy-MM-dd
log4j.appender.error.Threshold = error   
log4j.appender.error.append=true
log4j.appender.error.File=E:/code/log/error.loglog4j.logger.DEBUG=DEBUG
log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout     
log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  
log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd
log4j.appender.DEBUG.Threshold = DEBUG   
log4j.appender.DEBUG.append=true
log4j.appender.DEBUG.File=E:/code/log/dubug.log

log4j代码
private static final Logger logger = LoggerFactory.getLogger(IndexController.class);

3.application

# 指定log4j.properties配置文件路径
logging:config: classpath:log4j.properties

在这里插入图片描述
在这里插入图片描述

8.3使用AOP统一处理Web请求日志

一般项目都是基于AOP实现 或者elk实现的
它可以在我们的方法的前后实现拦截 减少打印日志代码的冗余性的问题
1.Maven依赖

<!-- springboot-aop -->	
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.AOP切面相关配置(直接拷贝即可)

package com.zhaoli.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;@Aspect
@Component
@Slf4j
public class WebLogAspect {//    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);/*** 切入点* com.zhaoli.controller.* 拦截该包下的所有类* com.zhaoli.controller.*.* 拦截该包下的所有类中的所有方法* (..)所有的方法参数*/@Pointcut("execution(public * com.zhaoli.controller.*.*(..))")public void webLog() {}/*** 前置通知 请求方法之前做拦截*/@Before("webLog()")public void doBefore(JoinPoint joinPoint) throws Throwable {// 接收到请求,记录请求内容ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();// 记录下请求内容log.info("URL : " + request.getRequestURL().toString());log.info("HTTP_METHOD : " + request.getMethod());log.info("IP : " + request.getRemoteAddr());Enumeration<String> enu = request.getParameterNames();while (enu.hasMoreElements()) {String name = (String) enu.nextElement();log.info("name:{},value:{}", name, request.getParameter(name));}}/*** 目标方法请求之后 打印(响应)信息*/@AfterReturning(returning = "ret", pointcut = "webLog()")public void doAfterReturning(Object ret) throws Throwable {// 处理完请求,返回内容log.info("RESPONSE : " + ret);}
}

9.其他内容

9.1使用@Scheduled创建定时任务

Spring Boot的主类(App类即启动类)中加入@EnableScheduling注解,启用定时任务的配置
package com.zhaoli.task;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
@Slf4j
public class ScheduledTasks {/*** 每隔三秒执行到 taskService()*/@Scheduled(fixedRate = 3000)public void taskService(){log.info("<<定时任务执行>>"+System.currentTimeMillis());}
}

在这里插入图片描述

加粗部分一般使用@Scheduled(cron = "0/2 * * * * *") 写法:
https://www.bejson.com/othertools/cron/
可以在此网站中查找双引号中的使用规范
在这里插入图片描述

9.2使用@Async实现异步调用

在 Spring Boot 应用的主类(App类即启动类)上添加 @EnableAsync 注解,用于启用 Spring 的异步执行功能。
需要执行异步方法上加入 @Async

具体来说,@Async 注解用于告诉 Spring 框架将被注解的方法放入一个任务执行器(Task Executor)中执行,而不是使用调用线程进行同步执行。任务执行器负责管理执行异步任务的线程池或者其他执行策略。
异步应用场景
@Async实际就是多线程封装的
异步线程执行方法有可能会非常消耗cpu的资源,所以大的项目建议使用
Mq异步实现。

整合线程池
异步注解配置类
com.zhaoli.config.ThreadPoolConfig (配置线程池,可直接拷贝)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;@Configuration
@EnableAsync
public class ThreadPoolConfig {/*** 每秒需要多少个线程处理?* tasks/(1/taskcost)*/private int corePoolSize = 3;/*** 线程池维护线程的最大数量* (max(tasks)- queueCapacity)/(1/taskcost)*/private int maxPoolSize = 3;/*** 缓存队列* (coreSizePool/taskcost)*responsetime*/private int queueCapacity = 10;/*** 允许的空闲时间* 默认为60*/private int keepAlive = 100;@Beanpublic TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 设置核心线程数executor.setCorePoolSize(corePoolSize);// 设置最大线程数executor.setMaxPoolSize(maxPoolSize);// 设置队列容量executor.setQueueCapacity(queueCapacity);// 设置允许的空闲时间(秒)//executor.setKeepAliveSeconds(keepAlive);// 设置默认线程名称executor.setThreadNamePrefix("thread-");// 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 等待所有任务结束后再关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}
}

代码案例
@Async("taskExecutor") 是一个Spring框架中的注解,用于将方法标记为异步执行的方法。

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;@Slf4j
@Component
public class MemberServiceAsync {@Async("taskExecutor") //指定线程池名称public String smsAsync() {log.info(">02<");try {log.info(">正在发送短信..<");Thread.sleep(3000);} catch (Exception e) {}log.info(">03<");return "短信发送完成!";}
}

注意失效问题
注意:如果异步注解写当前自己类,有可能aop会失效,无法拦截注解,最终导致异步注解失效,需要经过代理类调用接口;
所以需要将异步的代码单独抽取成一个类调用接口。

9.3全局捕获异常

@ExceptionHandler 表示拦截异常
@ControllerAdvicecontroller 的一个辅助类,最常用的就是作为全局异常处理的切面类
@ControllerAdvice 可以指定扫描范围
@ControllerAdvice 约定了几种可行的返回值,如果是直接返回 model 类的话,需要使用 @ResponseBody 进行 json 转换

  • 返回 String,表示跳到某个 view
  • 返回 modelAndView
  • 返回 model + @ResponseBody

全局捕获异常配置类

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;
import java.util.Map;@ControllerAdvice
public class MayiktExceptionHandler {/*** 拦截运行异常出现的错误~~~*/@ExceptionHandler(RuntimeException.class)@ResponseBodypublic Map<Object, Object> exceptionHandler() {Map<Object, Object> map = new HashMap<>();map.put("error", "500");map.put("msg", "系统出现错误~");return map;}
}

没使用之前
在这里插入图片描述

给用户显示这个页面很不友好
使用全局捕获异常配置类之后的页面
在这里插入图片描述

9.4发布打包

使用mvn package 打包
进入到项目所在目录 输入 mvn clean package 进行打包等待打包完成
在这里插入图片描述

显示这个即打包完成
在这里插入图片描述

在项目的目录中的 target 包下生成一个java-jar
在这里插入图片描述

使用java –jar 包的全路径地址
在这里插入图片描述

如果报错没有主清单,在pom文件中新增

<!-- 设置打包主清单属性 -->
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>repackage</goal></goals></execution></executions><configuration><!-- 启动类 --><mainClass>com.zhaoli.App</mainClass><excludes><exclude><groupId>junit</groupId><artifactId>junit</artifactId></exclude><exclude><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></exclude></excludes></configuration></plugin></plugins>
</build>

重新打包再运行
在这里插入图片描述
启动
在这里插入图片描述
在这里插入图片描述

成功运行
在这里插入图片描述

相关文章:

【实战教程】SpringBoot全面指南:快速上手到项目实战(SpringBoot)

文章目录 【实战教程】SpringBoot全面指南&#xff1a;快速上手到项目实战(SpringBoot)1. SpringBoot介绍1.1 SpringBoot简介1.2系统要求1.3 SpringBoot和SpringMVC区别1.4 SpringBoot和SpringCloud区别 2.快速入门3. Web开发3.1 静态资源访问3.2 渲染Web页面3.3 YML与Properti…...

LeetCode讲解篇之1043. 分隔数组以得到最大和

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 对于这题我们这么考虑&#xff0c;我们选择以数字的第i个元素做为分隔子数组的右边界&#xff0c;我们需要计算当前分隔子数组的长度为多少时能让数组[0, i]进行分隔数组的和最大 我们用数组f表示[0, i)区间内的…...

Python知识点:结合Python工具,如何使用TfidfVectorizer进行文本特征提取

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 如何使用Python的TfidfVectorizer进行文本特征提取 在自然语言处理&#xff08;…...

Diffusion models(扩散模型) 是怎么工作的

前言 给一个提示词, Midjourney, Stable Diffusion 和 DALL-E 可以生成很好看的图片&#xff0c;那么它们是怎么工作的呢&#xff1f;它们都用了 Diffusion models&#xff08;扩散模型&#xff09; 这项技术。 Diffusion models 正在成为生命科学等领域的一项尖端技术&…...

查找回收站里隐藏的文件

在Windows里&#xff0c;每个磁盘分区都有一个隐藏的回收站Recycle&#xff0c; 回收站里保存着用户删除的文件、图片、视频等数据&#xff0c;比如&#xff0c;C盘的回收站为C:\RECYCLE.BIN\&#xff0c;D盘的的回收站为D:\RECYCLE.BIN\&#xff0c;E盘的的回收站为E:\RECYCLE…...

[运维]2.elasticsearch-svc连接问题

Serverless 与容器决战在即&#xff1f;有了弹性伸缩就不一样了 - 阿里云云原生 - 博客园 当我部署好elasticsearch的服务后&#xff0c;由于个人习惯&#xff0c;一般服务会在name里带上svc&#xff0c;所以我elasticsearch服务的名字是elasticsearch-svc&#xff1a; [root…...

Ajax面试题:(第一天)

目录 1.说一下网络模型 2.在浏览器地址栏键入URL&#xff0c;按下回车之后会经历以下流程&#xff1a; 3.什么是三次握手和四次挥手&#xff1f; 4.http协议和https协议的区别 1.说一下网络模型 注&#xff1a;各层含义按自己理解即可 2.在浏览器地址栏键入URL&#xff0c;…...

数据仓库拉链表

数仓拉链表是数据仓库中常用的一种数据结构&#xff0c;用于记录维度表中某个属性的历史变化情况。在实际应用中&#xff0c;数仓拉链表可以帮助企业更好地进行数据分析和决策。 数仓拉链表&#xff08;Slowly Changing Dimension, SCD&#xff09;是一种用于处理维表中数据变化…...

【JVM】实战篇

1、内存调优 1.1 内存溢出和内存泄漏 内存泄漏&#xff08;memory leak&#xff09;&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在GC ROOT的引用链上&#xff0c;这个对象就不会被垃圾回收器回收&#xff0c;这种情况就称之为内存泄漏。 内存泄漏绝…...

2024年9月30日--10月6日(ue5肉鸽结束)

按照月计划&#xff0c;本周把ue肉鸽游戏完成&#xff0c;然后进行ue5太阳系 &#xff0c; 剩余14节&#xff0c;218分钟&#xff0c;如果按照10分钟的视频教程1小时进行完的话&#xff0c;则需要22小时&#xff0c;分布在10月2日-10月6日之间&#xff0c;每天44分钟的视频教程…...

【Python游戏开发】贪吃蛇游戏demo

准备步骤 项目开发使用【Mu 编辑器】 1.新建项目&#xff0c;并导入游戏图片 游戏编写 1.创建场景 SIZE 15 # 每个格子的大小 WIDTH SIZE * 30 # 游戏场景总宽度 HEIGHT SIZE * 30 # 游戏场景总高度def draw():screen…...

pytorch张量基础

引言张量的基础知识 张量的概念张量的属性张量的创建张量的操作 基本运算索引和切片形状变换自动微分 基本概念停止梯度传播张量的设备管理 检查和移动张量CUDA 张量高级操作 张量的视图广播机制分块和拼接张量的复制内存优化和管理 稀疏张量内存释放应用实例 线性回归神经网络…...

深入解析LlamaIndex Workflows【下篇】:实现ReAct模式AI智能体的新方法

之前我们介绍了来自LLM开发框架LlamaIndex的新特性&#xff1a;Workflows&#xff0c;一种事件驱动、用于构建复杂AI工作流应用的新方法&#xff08;参考&#xff1a;[深入解析LlamaIndex Workflows&#xff1a;构建复杂RAG与智能体工作流的新利器【上篇】]。在本篇中&#xff…...

要在 Git Bash 中使用 `tree` 命令,下载并手动安装 `tree`。

0、git bash 安装 git(安装,常用命令,分支操作,gitee,IDEA集成git,IDEA集成gitee,IDEA集成github,远程仓库操作) 1、下载并手动安装 tree 下载 tree.exe 从 tree for Windows 官方站点 下载 tree 的 Windows 可执行文件。tree for Window&#xff1a;https://gnuwin32.source…...

Linux的基本指令(1)

前提&#xff1a; a&#xff1a;博主是在云服务器上进行操作的 b&#xff1a;windows上普通文件在Linux中也叫作普通文件&#xff0c;但是windows上的文件夹&#xff0c;在Linux中叫作目录 c&#xff1a;文件 文件内容 文件属性(创建时间&#xff0c;修改时间&#xff0c;…...

JavaEE之多线程进阶-面试问题

一.常见的锁策略 锁策略不是指某一个具体的锁&#xff0c;所有的锁都可以往这些锁策略中套 1.悲观锁与乐观锁 预测所冲突的概率是否高&#xff0c;悲观锁为预测锁冲突的概率较高&#xff0c;乐观锁为预测锁冲突的概率更低。 2.重量级锁和轻量级锁 从加锁的开销角度判断&am…...

费曼学习法没有输出对象怎么办?

‌费曼学习法并不需要输出对象。‌费曼学习法的核心在于通过将所学知识以简明易懂的方式解释给自己听&#xff0c;从而加深对知识的理解和记忆。这种方法强调的是理解和反思的过程&#xff0c;而不是简单地通过输出&#xff08;如向他人解释&#xff09;来检验学习效果。费曼学…...

Hive优化操作(二)

Hive 数据倾斜优化 在使用 Hive 进行大数据处理时&#xff0c;数据倾斜是一个常见的问题。本文将详细介绍数据倾斜的概念、表现、常见场景及其解决方案。 1. 什么是数据倾斜&#xff1f; 数据倾斜是指由于数据分布不均匀&#xff0c;导致大量数据集中到某个节点或任务中&…...

销冠的至高艺术:让自己不像销售

若想在销售领域脱颖而出&#xff0c;首先是让自己超越传统销售的框架&#xff0c;成为客户心中不可多得的行业顾问与信赖源泉。这不仅是身份的蜕变&#xff0c;更是影响力与信任度质的飞跃。 销冠对客户只吸引不骚扰&#xff0c;不讲自己卖什么&#xff0c;只讲自己能解决什么…...

Hive数仓操作(十一)

一、Hive 日期函数 在日常的数据处理工作中&#xff0c;日期和时间的处理是非常常见的操作。Hive 提供了丰富的日期函数&#xff0c;能够帮助我们方便地进行日期和时间的计算。本文将详细介绍 Hive 中常用的日期函数&#xff0c;并通过具体的示例展示其用法和结果。 1. 获取当…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

高抗扰度汽车光耦合器的特性

晶台光电推出的125℃光耦合器系列产品&#xff08;包括KL357NU、KL3H7U和KL817U&#xff09;&#xff0c;专为高温环境下的汽车应用设计&#xff0c;具备以下核心优势和技术特点&#xff1a; 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计&#xff0c;确保在…...