springboot-入门

This commit is contained in:
法然
2022-11-21 11:54:51 +08:00
parent 1adf3c2cb6
commit d805c659e2
16 changed files with 1285 additions and 389 deletions

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

306
Java三方库/log4j.md Normal file
View File

@@ -0,0 +1,306 @@
https://blog.csdn.net/qq_43842093/article/details/122810961
### appender
* ConsoleAppender: 日志输出到控制台; FileAppender输出到文件
* RollingFileAppender输出到文件文件达到一定阈值时自动备份日志文件;
* DailyRollingFileAppender可定期备份日志文件默认一天一个文件也可设置为每分钟一个、每小时一个
* WriterAppender可自定义日志输出位置。
### 日志级别
一般日志级别包括ALLDEBUG INFO WARN ERRORFATALOFF
### 输出格式
1. org.apache.log4j.HTMLLayout以HTML表格形式布局
2. org.apache.log4j.PatternLayout可以灵活地指定布局模式
3. org.apache.log4j.SimpleLayout包含日志信息的级别和信息字符串
4. org.apache.log4j.TTCCLayout包含日志产生的时间、线程、类别等等信息
```
-X号: X信息输出时左对齐
%p: 输出日志信息优先级即DEBUGINFOWARNERRORFATAL,
%d: 输出日志时间点的日期或时间默认格式为ISO8601也可以在其后指定格式比如%d{yyy MMM dd HH:mm:ss,SSS}输出类似2002年10月18日 221028921
%r: 输出自应用启动到输出该log信息耗费的毫秒数
%c: 输出日志信息所属的类目,通常就是所在类的全名
%t: 输出产生该日志事件的线程名
%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程以及在代码中的行数。举例Testlog4.main (TestLog4.java:10)
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%: 输出一个"%"字符
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信息
%n: 输出一个回车换行符Windows平台为"/r/n"Unix平台为"/n"输出日志信息换行
可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
1)%20c指定输出category的名称最小的宽度是20如果category的名称小于20的话默认的情况下右对齐。
2)%-20c:指定输出category的名称最小的宽度是20如果category的名称小于20的话"-"号指定左对齐。
3)%.30c:指定输出category的名称最大的宽度是30如果category的名称大于30的话就会将左边多出的字符截掉但小于30的话也不会有空格。
4)%20.30c:如果category的名称小于20就补空格并且右对齐如果其名称长于30字符就从左边较远输出的字符截掉。
```
### 配置文件头
```
<?xml version="1.0" encoding="UTF-8"?>
//这行修改
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
或者
<?xml version="1.0" encoding="UTF-8"?>
//改为这个
<!DOCTYPE log4j:configuration PUBLIC
"-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
```
### XML配置文件实例
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!--<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">-->
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- 日志输出到控制台 -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<!-- 日志输出格式 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[日志信息优先级:%p][输出自应用启动到输出该log信息耗费的毫秒数%r][%d{yyyy-MM-dd HH:mm:ss SSS}][日志信息所属的类目,通常就是所在类的全名:%c]-[产生该日志事件的线程名:%t]-[代码中指定的消息,产生的日志具体信息:%m]%n-[日志事件的发生位置:%l]"/>
</layout>
<!--过滤器设置输出的级别-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- 设置日志输出的最小级别 -->
<param name="levelMin" value="INFO"/>
<!-- 设置日志输出的最大级别 -->
<param name="levelMax" value="ERROR"/>
</filter>
</appender>
<!-- 输出日志到文件 -->
<appender name="fileAppender" class="org.apache.log4j.FileAppender">
<!-- 输出文件全路径名-->
<param name="File" value="/logs/fileAppender.log"/>
<!--是否在已存在的文件追加写默认时true若为false则每次启动都会删除并重新新建文件-->
<param name="Append" value="false"/>
<param name="Threshold" value="INFO"/>
<!--是否启用缓存默认false-->
<param name="BufferedIO" value="false"/>
<!--缓存大小,依赖上一个参数(bufferedIO), 默认缓存大小8K -->
<param name="BufferSize" value="512"/>
<!-- 日志输出格式 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[日志信息优先级:%p][输出自应用启动到输出该log信息耗费的毫秒数%r][%d{yyyy-MM-dd HH:mm:ss SSS}][日志信息所属的类目,通常就是所在类的全名:%c]-[产生该日志事件的线程名:%t]-[代码中指定的消息,产生的日志具体信息:%m]%n-[日志事件的发生位置:%l]"/>
</layout>
</appender>
<!-- 输出日志到文件,当文件大小达到一定阈值时,自动备份 -->
<!-- FileAppender子类 -->
<appender name="rollingAppender" class="org.apache.log4j.RollingFileAppender">
<!-- 日志文件全路径名 -->
<param name="File" value="/logs/RollingFileAppender.log" />
<!--是否在已存在的文件追加写默认时true若为false则每次启动都会删除并重新新建文件-->
<param name="Append" value="true" />
<!-- 保存备份日志的最大个数默认值是1 -->
<param name="MaxBackupIndex" value="10" />
<!-- 设置当日志文件达到此阈值的时候自动回滚单位可以是KBMBGB默认单位是KB默认值是10MB -->
<param name="MaxFileSize" value="10MB" />
<!-- 设置日志输出的样式 -->`
<layout class="org.apache.log4j.PatternLayout">
<!-- 日志输出格式 -->
<param name="ConversionPattern" value="[日志信息优先级:%p][输出自应用启动到输出该log信息耗费的毫秒数%r][%d{yyyy-MM-dd HH:mm:ss SSS}][日志信息所属的类目,通常就是所在类的全名:%c]-[产生该日志事件的线程名:%t]-[代码中指定的消息,产生的日志具体信息:%m]%n-[日志事件的发生位置:%l]" />
</layout>
</appender>
<!-- 日志输出到文件,可以配置多久产生一个新的日志信息文件 -->
<appender name="dailyRollingAppender" class="org.apache.log4j.DailyRollingFileAppender">
<!-- 文件文件全路径名 -->
<param name="File" value="/logs/dailyRollingAppender.log"/>
<param name="Append" value="true" />
<!-- 设置日志备份频率,默认:为每天一个日志文件 -->
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<!--每分钟一个备份-->
<!--<param name="DatePattern" value="'.'yyyy-MM-dd-HH-mm'.log'" />-->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[日志信息优先级:%p][输出自应用启动到输出该log信息耗费的毫秒数%r][%d{yyyy-MM-dd HH:mm:ss SSS}][日志信息所属的类目,通常就是所在类的全名:%c]-[产生该日志事件的线程名:%t]-[代码中指定的消息,产生的日志具体信息:%m]%n-[日志事件的发生位置:%l]"/>
</layout>
</appender>
<!--
1. 指定logger的设置additivity是否遵循缺省的继承机制
2. 当additivity="false"时root中的配置就失灵了不遵循缺省的继承机制
-->
<logger name="logTest" additivity="false">
<level value ="debug"/>
<appender-ref ref="dailyRollingAppender"/>
</logger>
<!-- 根logger的设置若代码中未找到指定的logger则会根据继承机制使用根logger-->
<root>
<level value ="debug"/>
<appender-ref ref="console"/>
<appender-ref ref="fileAppender"/>
<appender-ref ref="rollingAppender"/>
<appender-ref ref="dailyRollingAppender"/>
</root>
</log4j:configuration>
```
### properties配置文件
* 配置根LoggerLog4j建议只使用四个级别优 先级从高到低分别是ERROR、WARN、INFO、DEBUG。
```
log4j.rootLogger = [ level ] , appenderName, appenderName, …
```
* 配置appender
```
org.apache.log4j.ConsoleAppender控制台
org.apache.log4j.FileAppender文件
org.apache.log4j.DailyRollingFileAppender每天产生一个日志文件
org.apache.log4j.RollingFileAppender文件大小到达指定尺寸的时候产生一个新的文件
org.apache.log4j.WriterAppender将日志信息以流格式发送到任意指定的地方
```
* 配置日志信息的格式
```
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
… log4j.appender.appenderName.layout.option = valueN
org.apache.log4j.HTMLLayout以HTML表格形式布局
org.apache.log4j.PatternLayout可以灵活地指定布局模式
org.apache.log4j.SimpleLayout包含日志信息的级别和信息字符串
org.apache.log4j.TTCCLayout包含日志产生的时间、线程、类别等等信息
%p 输出优先级即DEBUGINFOWARNERRORFATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符Windows平台为“rn”Unix平台为“n”
%d 输出日志时间点的日期或时间默认格式为ISO8601也可以在其后指定格式比如%d{yyy MMM dd HH:mm:ss,SSS}输出类似2002年10月18日 221028921
%l 输出日志事件的发生位置包括类目名、发生的线程以及在代码中的行数。举例Testlog4.main(TestLog4.java:10)
```
```properties
log4j.rootLogger=DEBUG,console,dailyFile,im
log4j.additivity.org.apache=true
# 控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 日志文件(logFile)
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 回滚文件(rollingFile)
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 定期回滚日志文件(dailyFile)
log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.Threshold=DEBUG
log4j.appender.dailyFile.ImmediateFlush=true
log4j.appender.dailyFile.Append=true
log4j.appender.dailyFile.File=D:/logs/log.log4j
log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
log4j.appender.dailyFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 应用于socket
log4j.appender.socket=org.apache.log4j.RollingFileAppender
log4j.appender.socket.RemoteHost=localhost
log4j.appender.socket.Port=5001
log4j.appender.socket.LocationInfo=true
# Set up for Log Factor 5
log4j.appender.socket.layout=org.apache.log4j.PatternLayout
log4j.appender.socket.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
# 发送日志到指定邮件
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=FATAL
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From = xxx@mail.com
log4j.appender.mail.SMTPHost=mail.com
log4j.appender.mail.Subject=Log4J Message
log4j.appender.mail.To= xxx@mail.com
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
log4j.appender.mail.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 应用于数据库
log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.URL=jdbc:mysql://localhost:3306/test
log4j.appender.database.driver=com.mysql.jdbc.Driver
log4j.appender.database.user=root
log4j.appender.database.password=
log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) --> [%t] %l: %m %x %n')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
log4j.appender.database.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
```
### 使用log4j
* 获取日志记录器
```
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )
```
* 读取配置文件
```java
BasicConfigurator.configure () 自动快速地使用缺省Log4j环境
PropertyConfigurator.configure ( String configFilename) 读取使用Java的特性文件编写的配置文件
DOMConfigurator.configure ( String filename ) 读取XML形式的配置文件
```
* 插入日志记录
```java
Logger.debug ( Object message ) ;
Logger.info ( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;
```

128
Java三方库/slf4j.md Normal file
View File

@@ -0,0 +1,128 @@
## 原理说明
slf4j是门面模式的典型应用因此在讲slf4j前我们先简单回顾一下门面模式
门面模式,其核心为外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。用一张图来表示门面模式的结构为:
![](image/2022-11-15-14-38-18.png)
门面模式的核心为Facade即门面对象门面对象核心为几个点
* 知道所有子角色的功能和责任
* 将客户端发来的请求委派到子系统中,没有实际业务逻辑
* 不参与子系统内业务逻辑的实现
解决这个问题的方式就是引入一个适配层由适配层决定使用哪一种日志系统而调用端只需要做的事情就是打印日志而不需要关心如何打印日志slf4j或者commons-logging就是这种适配层slf4j是本文研究的对象。
从上面的描述我们必须清楚地知道一点slf4j只是一个日志标准并不是日志系统的具体实现。理解这句话非常重要slf4j只做两件事情
* 提供日志接口
* 提供获取具体日志对象的方法
slf4j的直接/间接实现有slf4j-simple、logback、slf4j-log4j12。slf4j-simple、logback都是slf4j的具体实现log4j并不直接实现slf4j但是有专门的一层桥接slf4j-log4j12来实现slf4j。
> log4j本身并不提供slf4j的实现自己可以独立使用。但是logback不行。
### LoggerFactory源码分析
> 自己阅读了源码
在编译的时候,绑定具体的日志试下类。并且当前环境应该只有一个具体的日志实现类。
* slf4j-api作为slf4j的接口类使用在程序代码中这个包提供了一个Logger类和LoggerFactory类Logger类用来打日志LoggerFactory类用来获取Loggerslf4j-log4j是连接slf4j和log4j的桥梁怎么连接的呢我们看看slf4j的LoggerFactory类的getLogger函数的源码
```
/**
* Return a logger named corresponding to the class passed as parameter, using
* the statically bound {@link ILoggerFactory} instance.
*
* @param clazz the returned logger will be named after clazz
* @return logger
*/
public static Logger getLogger(Class clazz) {
return getLogger(clazz.getName());
}
/**
* Return a logger named according to the name parameter using the statically
* bound {@link ILoggerFactory} instance.
*
* @param name The name of the logger.
* @return logger
*/
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
performInitialization();
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
// support re-entrant behavior.
// See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
return TEMP_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
```
* LoggerFactory.getLogger()首先获取一个ILoggerFactory接口然后使用该接口获取具体的Logger。获取ILoggerFactory的时候用到了一个StaticLoggerBinder类仔细研究我们会发现StaticLoggerBinder这个类并不是slf4j-api这个包中的类而是slf4j-log4j包中的类这个类就是一个中间类它用来将抽象的slf4j变成具体的log4j也就是说具体要使用什么样的日志实现方案就得靠这个StaticLoggerBinder类。再看看slf4j-log4j包种的这个StaticLoggerBinder类创建ILoggerFactory长什么样子
```java
private final ILoggerFactory loggerFactory;
private StaticLoggerBinder() {
loggerFactory = new Log4jLoggerFactory();
try {
Level level = Level.TRACE;
} catch (NoSuchFieldError nsfe) {
Util
.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
}
}
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
}
```
* 可以看到slf4j-log4j中的StaticLoggerBinder类创建的ILoggerFactory其实是一个org.slf4j.impl.Log4jLoggerFactory这个类的getLogger函数是这样的
```
public Logger getLogger(String name) {
Logger slf4jLogger = loggerMap.get(name);
if (slf4jLogger != null) {
return slf4jLogger;
} else {
org.apache.log4j.Logger log4jLogger;
if(name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME))
log4jLogger = LogManager.getRootLogger();
else
log4jLogger = LogManager.getLogger(name);
Logger newInstance = new Log4jLoggerAdapter(log4jLogger);
Logger oldInstance = loggerMap.putIfAbsent(name, newInstance);
return oldInstance == null ? newInstance : oldInstance;
}
```

View File

@@ -384,4 +384,27 @@ public static void main(String[] args) {
//法二用Lambda
map.forEach((key,value)-> System.out.println("key:"+key+"value:"+value));
}
```
```
## 5 jdk中的函数式接口
```java
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
```
jdk中任意地方可以接收该接口的对象。是一个标准的无参、无返回值的函数。传入任何无参无返回值的函数即可执行。

View File

@@ -0,0 +1,135 @@
### mybatis-configuration.xml
| 设置名 | 描述 | 有效值 | 默认值 |
|---|---|---|---|
| cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存 | true | false | true |
| lazyLoadingEnabled | 延迟加载的全局开关。当开启时所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态 | true | false | false |
| aggressiveLazyLoading | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。否则,每个延迟加载属性会按需加载 | true | false | false(在 3.4.1 及之前的版本中默认为 true) |
| multipleResultSetsEnabled | 是否允许单个语句返回多结果集(需要数据库驱动支持) | true | false | true |
| useColumnLabel | 使用列标签代替列明。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察 | true | false | true |
| useGeneratedKeys | 允许JDBC支持自动生成主键需要数据库驱动支持。如果设置为true将强制使用自动生成主键。尽管一些数据库驱动不支持此特性但仍可正常工作(如Derby) | true | false | false |
| autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射PARTIAL ​只会自动映射没有定义嵌套结果映射的字段。 FULL ​会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
| autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或未知属性类型)的行为。 NONE: 不做任何反应
WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN FAILING: 映射失败 (抛出 SqlSessionException) | NONE, WARNING, FAILING | NONE |
| defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器REUSE 执行器会重用预处理语句PreparedStatement BATCH ​执行器不仅重用语句还会执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
| defaultStatementTimeout | 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
| defaultFetchSize | 为驱动的结果集获取数量fetchSize设置一个建议值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
| defaultResultSetType | 指定语句默认的滚动策略。(新增于 3.5.2 | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT等同于未设置 | 未设置 (null) |
| safeRowBoundsEnabled | 是否允许在嵌套语句中使用分页RowBounds。如果允许使用则设置为 false。 | true | false | False |
| safeResultHandlerEnabled | 是否允许在嵌套语句中使用结果处理器ResultHandler。如果允许使用则设置为 false。 | true | false | True |
| mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN ​映射到经典 Java 属性名 aColumn。 | true | false | False |
| localCacheScope | MyBatis 利用本地缓存机制Local Cache防止循环引用和加速重复的嵌套查询。 默认值为 SESSION会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT本地缓存将仅用于执行语句对相同 SqlSession ​的不同查询将不会进行缓存。 | SESSION | STATEMENT | SESSION |
| jdbcTypeForNull | 当没有为参数指定特定的 JDBC类型时空值的默认 JDBC类型。 某些数据库驱动需要指定列的 JDBC类型多数情况直接用一般类型即可比如 NULLVARCHAR ​或 OTHER。 | JdbcType 常量常用值NULL、VARCHAR 或 OTHER。 | OTHER |
| lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
| defaultScriptingLanguage | 指定动态 SQL 生成使用的默认脚本语言。 | 一个类型别名或全限定类名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
| defaultEnumTypeHandler | 指定Enum使用的默认TypeHandler新增于 3.4.5 | 一个类型别名或全限定类名。 | org.apache.ibatis.type.EnumTypeHandler |
| callSettersOnNulls | 指定当结果集中值为 null ​的时候是否调用映射对象的 settermap 对象时为 put方法这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型int、boolean 等)是不能设置成 null 的。 | true | false | false |
| returnInstanceForEmptyRow | 当返回行的所有列都是空时MyBatis默认返回 null。 当开启这个设置时MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2 | true | false | false |
| logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 |
| logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J(deprecated since 3.5.9) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
| proxyFactory | 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST MyBatis 3.3 以上) |
| vfsImpl | 指定 VFS 的实现 | 自定义 VFS 的实现的类全限定名,以逗号分隔。 | 未设置 |
| useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1 | true | false | true |
| configurationFactory | 指定一个提供 Configuration实例的类。 这个被返回的 Configuration ​实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3 | 一个类型别名或完全限定类名。 | 未设置 |
| shrinkWhitespacesInSql | 从SQL中删除多余的空格字符。请注意这也会影响SQL中的文字字符串。 (新增于 3.5.5) | true | false | false |
| defaultSqlProviderType | 指定一个包含提供程序方法的 sql 提供程序类(自 3.5.6 起)。 当省略这些属性时,此类适用于 sql 提供程序注释(例如 @SelectProvider​)上的类型(或值)属性。 | 类型别名或完全限定的类名 | 未设置 |
| nullableOnForEach | 指定'foreach'标记上的'nullable'属性的默认值。(自 3.5.9 起) | true | false | false |
### 配置多数据源——独立数据源
1两个或多个数据库没有相关性各自独立其实这种可以作为两个项目来开发。比如在游戏开发中一个数据库是平台数据库其它还有平台下的游戏对应的数据库
2两个或多个数据库是master-slave的关系比如有mysql搭建一个 master-master其后又带有多个slave或者采用MHA搭建的master-slave复制
目前我所知道的 Spring 多数据源的搭建大概有两种方式,可以根据多数据源的情况进行选择。
采用spring配置文件直接配置多个数据源.比如针对两个数据库没有相关性的情况可以采用直接在spring的配置文件中配置多个数据源然后分别进行事务的配置如下所示
```
<context:component-scan base-package="net.aazj.service,net.aazj.aop" />
<context:component-scan base-package="net.aazj.aop" />
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config/db.properties" />
<!-- 配置数据源 -->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="0" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="20" />
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="20" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="0" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:config/mybatis-config.xml" />
<property name="mapperLocations" value="classpath*:config/mappers/**/*.xml" />
</bean>
<!-- Transaction manager for a single JDBC DataSource -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="net.aazj.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- Enables the use of the @AspectJ style of Spring AOP -->
<aop:aspectj-autoproxy/>
<!-- ===============第二个数据源的配置=============== -->
<bean name="dataSource_2" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc_url_2}" />
<property name="username" value="${jdbc_username_2}" />
<property name="password" value="${jdbc_password_2}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="0" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="20" />
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="20" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="0" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
</bean>
<bean id="sqlSessionFactory_slave" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource_2" />
<property name="configLocation" value="classpath:config/mybatis-config-2.xml" />
<property name="mapperLocations" value="classpath*:config/mappers2/**/*.xml" />
</bean>
<!-- Transaction manager for a single JDBC DataSource -->
<bean id="transactionManager_2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource_2" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager_2" />
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="net.aazj.mapper2" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory_2"/>
</bean>
```
### 配置数据源——主从数据源

View File

@@ -24,9 +24,9 @@ springboot + springcloud
3. 负载均衡和任务调度
4. 服务容错——流量控制和熔断
5. 配置管理——配置中心
6. 服务监控
7. 链路追踪
8. 日志管理
6. 服务监控——RMS
7. 链路追踪——log
8. 日志管理——云图log
### 云原生
@@ -39,6 +39,8 @@ springboot + springcloud
6. 流量治理
![](image/2022-11-17-09-35-48.png)
## 2 springboot概述
@@ -56,7 +58,7 @@ Spring Boot 是基于 Spring 框架基础上推出的一个全新的框架, 旨
4. 自动化配置 Spring 相关功能,以及第三方库;
5. 提供诸如指标,健康检查, 外部化配置等功能;
6. "零配置",再也不需要手写地狱般的 XML 配置了;
7. java8 适配器设计模式。接口有了默认实现。
#### 框架特点
@@ -64,189 +66,12 @@ Spring Boot 是基于 Spring 框架基础上推出的一个全新的框架, 旨
* IOC控制反转
* AOP面向切面
## 3 操作入门
## 3 Springboot的作用
### maven设置
* 配置maven的Aliyun镜像和jdk版本
```xml
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
```
### 创建maven工程
```
mvn archetype:generate
```
### 引入依赖
```
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
```
### 创建主程序
```java
/**
* 主程序类
* @SpringBootApplication这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
```
### 编写业务逻辑
```java
@RestController
public class HelloController {
@RequestMapping("/hello")
public String handle01(){
return "Hello, Spring Boot 2!";
}
}
```
### 测试
直接运行main方法
### 配置
application.properties
```
server.port=8888
```
### 简化部署
```xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
```
## 4 工程结构
### 推荐工程结构
```
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
| +- CustomerController.java
|
```
* root packagecom.example.myproject所有的类和其他package都在root package之下。
* 应用主类Application.java该类直接位于root package下。通常我们会在应用主类中做一些框架配置扫描等配置我们放在root package下可以帮助程序减少手工配置来加载到我们希望被Spring加载的内容
* com.example.myproject.domain包用于定义实体映射关系与数据访问相关的接口和实现
* com.example.myproject.service包用于编写业务逻辑相关的接口与实现
* com.example.myproject.web用于编写Web层相关的实现比如Spring MVC的Controller等
> Spring Boot的应用主类会自动扫描root package以及所有子包下的所有类来进行初始化。
### 非典型结构下的初始化
1. 使用@ComponentScan注解指定具体的加载包
```java
@SpringBootApplication
@ComponentScan(basePackages="com.example")
public class Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
}
```
2. 使用@Bean注解来初始化。在主类中进行初始化。
```java
@SpringBootApplication
public class Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
@Bean
public CustomerController customerController() {
return new CustomerController();
}
}
```
## 5 自动配置原理
### maven继承关系
### 依赖管理
* 在parent中管理版本信息
* 几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
```xml
依赖管理
<parent>
@@ -262,5 +87,43 @@ public class Bootstrap {
<version>2.3.4.RELEASE</version>
</parent>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
```
```
### 自动配置
> 通过java代码的方式配置好其他组件。它在自动配置领域主要做了以下事情
> * 默认的自动配置。对于所有组件,都指定了默认的约定俗称的最优的自动配置,用户可以不了解具体的配置项,开箱即用,按照约定完成业务逻辑即可。
> * 可控的自动配置。对于所有组件都提供了开放的自动配置接口xxxProperties中读取并加载用户的配置属性灵活地集成各种框架高效快速定制化。
> * 自定义自动配置。对于用户自定义的模块和组件springboot提供了一套自动配置的解决方案通过springboot的自动配置注解完成用户自己的模块的自动配置。十分方便。
> 从初阶的默认配置使用通过配置文件定制化使用借用springboot实现第三方模块自动配置的机制实现自定义模块自动配置总共包括三个层次和阶段。
例如能够自动引入并配置好tomcat
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
```
* 自动引入并配置好SpringMVC引入SpringMVC的组件
* 自动配置好web常见的功能
* 默认的包结构(配置好了默认的扫描路径)
```java
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
```
* 各种配置拥有默认值
* 默认配置最终都是映射到某个类上MultipartProperties
* 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
* 按需加载所有自动配置项
* 非常多的starter
* 引入了哪些场景这个场景的自动配置才会开启
* SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面

View File

@@ -1,28 +1,62 @@
## 1 创建一个springboot项目
## 1 创建项目
1. 创建Maven工程
2. 引入依赖pom.xml
1. 包括`<parent>`下是springboot的标签。`dependencies`下是相关的依赖。
### maven设置
* 配置maven的Aliyun镜像和jdk版本
```xml
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
```
### 创建maven工程
```
mvn archetype:generate
```
### 引入依赖
```
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</dependencies>
```
3. 创建主程序
```
### 创建主程序
```java
/**
* 主程序类
* @SpringBootApplication这是一个SpringBoot应用
@@ -35,9 +69,11 @@ public class MainApplication {
}
}
```
4. 编写具体业务
```
### 编写业务逻辑
```java
@RestController
public class HelloController {
@@ -50,34 +86,108 @@ public class HelloController {
}
```
5. 运行测试
6. 简化配置 application.properties
### 测试
直接运行main方法
### 配置
application.properties
```
server.port=8888
```
7. 简化部署
1. 把项目打包成jar包直接在目标服务器程序执行即可。
```
### 简化部署
```xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
```
## 2 工程结构
1. 主程序Main.java
2. 业务程序Controller.java
3. maven依赖pom.xml
4. 配置Springboot项目application.properties是Spring的集中配置中心包括项目相关的所有配置。
### 推荐工程结构
```
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
| +- CustomerController.java
|
```
* root packagecom.example.myproject所有的类和其他package都在root package之下。
* 应用主类Application.java该类直接位于root package下。通常我们会在应用主类中做一些框架配置扫描等配置我们放在root package下可以帮助程序减少手工配置来加载到我们希望被Spring加载的内容
* com.example.myproject.domain包用于定义实体映射关系与数据访问相关的接口和实现
* com.example.myproject.service包用于编写业务逻辑相关的接口与实现
* com.example.myproject.web用于编写Web层相关的实现比如Spring MVC的Controller等
> Spring Boot的应用主类会自动扫描root package以及所有子包下的所有类来进行初始化。
## 3 依赖管理
### 非典型结构下的初始化
1. 使用@ComponentScan注解指定具体的加载包
```java
@SpringBootApplication
@ComponentScan(basePackages="com.example")
public class Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
}
```
2. 使用@Bean注解来初始化。在主类中进行初始化。
```java
@SpringBootApplication
public class Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
@Bean
public CustomerController customerController() {
return new CustomerController();
}
}
```
## 3 两大特性——依赖管理
### 依赖管理的原理
通过父项目进行依赖管理。通过starter进行依赖导入。
```xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
```
1. mypom.xml
2. parent -- spring-boot-starter-parent
@@ -86,8 +196,63 @@ server.port=8888
1. 几乎声明了所有的版本查看Spring-boot-dependencies中的版本。可以自定义properties标签修改版本号。
2. stater场景启动器。自动引入相关的所有依赖。可以自定义场景启动器所有场景启动器最基本的以来。spring-boot-starter。引入依赖一部分可以不写版本号。引入非版本仲裁的版本号必须要写。
### spring-boot-starter-web的依赖树
* spring-boot-starter-web
* spring-boot相关的依赖
* +logging依赖
* +jason依赖
* +tomcat依赖
* web/webmvc相关的依赖
## 4 自动配置
* 新快捷键
```
cmd+B 声明和引用相互跳转
cmd+alt+B 实现和引用相互跳转
cmd+[/ cmd+] 前进后退
cmd+U 父项目
```
* 依赖树
![](image/2022-11-18-09-53-55.png)
```
[INFO] \- org.springframework.boot:spring-boot-starter-web:jar:2.3.4.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter:jar:2.3.4.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot:jar:2.3.4.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.3.4.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-logging:jar:2.3.4.RELEASE:compile
[INFO] | | +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] | | | +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] | | | \- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.13.3:compile
[INFO] | | | \- org.apache.logging.log4j:log4j-api:jar:2.13.3:compile
[INFO] | | \- org.slf4j:jul-to-slf4j:jar:1.7.30:compile
[INFO] | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] | +- org.springframework:spring-core:jar:5.2.9.RELEASE:compile
[INFO] | | \- org.springframework:spring-jcl:jar:5.2.9.RELEASE:compile
[INFO] | \- org.yaml:snakeyaml:jar:1.26:compile
[INFO] +- org.springframework.boot:spring-boot-starter-json:jar:2.3.4.RELEASE:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.11.2:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.11.2:compile
[INFO] | | \- com.fasterxml.jackson.core:jackson-core:jar:2.11.2:compile
[INFO] | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.11.2:compile
[INFO] | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.11.2:compile
[INFO] | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.11.2:compile
[INFO] +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.3.4.RELEASE:compile
[INFO] | +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.38:compile
[INFO] | +- org.glassfish:jakarta.el:jar:3.0.3:compile
[INFO] | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.38:compile
[INFO] +- org.springframework:spring-web:jar:5.2.9.RELEASE:compile
[INFO] | \- org.springframework:spring-beans:jar:5.2.9.RELEASE:compile
[INFO] \- org.springframework:spring-webmvc:jar:5.2.9.RELEASE:compile
[INFO] +- org.springframework:spring-aop:jar:5.2.9.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:5.2.9.RELEASE:compile
[INFO] \- org.springframework:spring-expression:jar:5.2.9.RELEASE:compile
```
## 4 两大特性——自动配置
### 自动配置的体现
1. 自动配好了SpringMVC
1. 引入了SpringMVC全套组件
@@ -99,7 +264,8 @@ server.port=8888
4. 按需加载所有的自动配置自动配置都在spring-boot-autoconfigure包中
### @ConfigurationProperties
@ConfigurationProperties简介
@ConfigurationProperties是springboot提供读取配置文件的一个注解
它是实现了BeanPostProcessor接口在bean被实例化后会调用后置处理递归的查找属性通过反射注入值对大多数属性而言强制需提供其setter和getter方法。

View File

@@ -0,0 +1,221 @@
# Bean配置文件
> * bean配置文件spring配置bean的文件。
> * java配置文件通过@Configuration加载
> * 原生配置文件xml定义的配置文件
> * 属性配置文件spring配置key-value的文件
## 1 注解说明
### 注解体系
1. 元注解@Rentention @Docemented,@Inherited,@Target
2. JDK标准注解
3. Spring标准注解@Bean @Component @Serivce,@Controller,@Configuration,@Import,@Autowire
4. springboot补充注解
### @SpringbootConfiguration开启自动配置
```
@SpringBootConfiguration springboot启动
@EnableAutoConfiguration 通过properties自动加载
@ComponentScan("com.atguigu.boot")扫描范围
```
springboot项目中的启动注解。
### @Configuration配置文件
1. 配置类里边使用@Bean标注在方法上,给容器注册组件,默认也是单实例模式。
2. 配置类本身也是组件相当于将组件注册到Spring当中。即把类的对象交给Spring管理。
3. proxybeanMethods:代理bean方法将配置类的中的方法设置为单例模式。可以解决组件间的依赖问题。默认为true使用spring中的方法代理原方法不会创建新的对象。
1. fullproxyBeanMehtods=true
2. liteproxyBeanMethods=false)
```java
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
################################@Configuration测试代码如下########################################
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
public class MainApplication {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
//3、从容器中获取组件
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:"+(tom01 == tom02));
//4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
//保持组件单实例
User user = bean.user01();
User user1 = bean.user01();
System.out.println(user == user1);
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:"+(user01.getPet() == tom));
}
}
```
### @Bean
在java配置文件中装配bean
1. 配置类实用@Bean标注方法上给容器注册组件默认也是单实例。id默认为方法名。可以通过参数指定
2. 外部类可以从Spring的容器中取出在Configuration类中注册的实例。而且都是单实例对象。
```
@Component @Controller @Service @Repository 都是以前的用法
```
### @Import
在java配置文件中导入bean
1. 将指定的组件导入到组件。给容器中自动创建指定类型的无参构造的组件。
2. 默认组件的名字是全类名。即包括包和类的名字。
```java
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}
```
三种导入类的方法对比
* 每个bean有名称和类型。没有id之说。名称必须唯一。
* @Bean导入的bena默认名称是方法名称
* @Import导入的bean默认是全类名
* @Component导入的bean默认是类名小写首字母
* @Component和@Import是不会冲突,如果已经通过@Component导入的bean(优先级更高)不会通过@Import重复导入
### ImportResource
导入原生配置文件
```xml
======================beans.xml=========================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="haha" class="com.atguigu.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="hehe" class="com.atguigu.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>
```
```java
@ImportResource("classpath:beans.xml")
public class MyConfig {}
======================测试=================
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha"+haha);//true
System.out.println("hehe"+hehe);//true
```
### @conditional
1. 条件装配。满足Conditional指定的条件则进行组件注入。
![](image/2022-11-12-15-49-46.png)
* @ConditionalOnBean(name="bean")当容器中存在指定名称的容器的时候,才会进行注册。
```xml
@=====================测试条件装配==========================
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
//@ConditionalOnBean(name = "tom")
@ConditionalOnMissingBean(name = "tom")
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom22")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
boolean tom = run.containsBean("tom");
System.out.println("容器中Tom组件"+tom);
boolean user01 = run.containsBean("user01");
System.out.println("容器中user01组件"+user01);
boolean tom22 = run.containsBean("tom22");
System.out.println("容器中tom22组件"+tom22);
}
```

View File

@@ -1,80 +0,0 @@
## 注解说明
注解体系
1. 元注解@Rentention @Docemented,@Inherited,@Target
2. JDK标准注解
3. Spring标准注解@Bean @Component @Serivce,@Controller,@Configuration,@Import,@Autowire
4. springboot补充注解
### @SpringbootConfiguration
```
@SpringBootConfiguration springboot启动
@EnableAutoConfiguration 通过properties自动加载
@ComponentScan("com.atguigu.boot")扫描范围
```
springboot项目中的启动注解。
### @Configuration&@Bean
1. 配置类本身也是组件相当于将组件注册到Spring当中。即把类的对象交给Spring管理。
2. proxybeanMethods:代理bean方法。可以解决组件间的依赖问题。如果为falseSpringboot不会检查配置类中组件间的依赖对于依赖的其他对象直接创建新的对象。true的时候每次运行都会检查配置中组件间的依赖不会创建新的对象。
1. fullproxyBeanMehtods=true
2. liteproxyBeanMethods=false)
### @Bean
1. 配置类实用@Bean标注方法上给容器注册组件默认也是单实例。id默认为方法名。可以通过参数指定
2. 外部类可以从Spring的容器中取出在Configuration类中注册的实例。而且都是单实例对象。
```
@Component @Controller @Service @Repository 都是以前的用法
```
### @Import
1. 将指定的组件导入到组件。给容器中自动创建指定类型的无参构造的组件。
2. 默认组件的名字是全类名。即包括包和类的名字。
### @conditional
1. 条件装配。满足Conditional指定的条件则进行组件注入。
![](image/2022-11-12-15-49-46.png)
* @ConditionalOnBean(name="bean")当容器中存在指定名称的容器的时候,才会进行注册。
```
@ConditionalOnBean(name="")
```
### @ImportResource
1. 在一个配置类中导入xml中的配置文件。
```
@ImportResource(classpath:"hello.xml")
```
### @ConfigurationProperties
1. 只有在容器中的组件才会有Springboot的强大功能。
2. 从配置文件中自动加载进行属性配置然后使用Componet注册
```
@Component
@ConfigurationProperties(prefix="mycar",)
class Car(){
}
```
### @EnableConfigurationProperties
1. 在配置类上开启属性配置功能。开启car的属性配置功能
2. 该中方法对配置类进行修改然后装配。不需要修改类本身的代码。
```
@EnableConfigurationProperties(Car.class)
class MyConfig{
}
```
### @Autowired
1. 容器中的自动注入。

View File

@@ -1,3 +1,10 @@
# 属性配置文件
> * bean配置文件spring配置bean的文件。
> * java配置文件通过@Configuration加载
> * 原生配置文件xml定义的配置文件
> * 属性配置文件spring配置key-value的文件
## 1 properties配置基础
### properties默认配置文件
@@ -114,8 +121,8 @@ k: v
```
行内写法: k: {k1:v1,k2:v2,k3:v3}
#或
k:
k1: v1
k:
k1: v1
k2: v2
k3: v3
```
@@ -236,10 +243,27 @@ java -jar xxx.jar --server.port=8888
1. 在@Configuration注解修改的类中,通过@PropertySource注解定义的属性
1. 应用默认属性使用SpringApplication.setDefaultProperties定义的内容1.
## 5 自定义配置文件/加载配置文件/属性绑定
## 5 配置绑定
### 使用Java程序读取
如何使用Java读取到properties文件中的内容并且把它封装到JavaBean中以供随时使用
```java
public class getProperties {
public static void main(String[] args) throws FileNotFoundException, IOException {
Properties pps = new Properties();
pps.load(new FileInputStream("a.properties"));
Enumeration enum1 = pps.propertyNames();//得到配置文件的名字
while(enum1.hasMoreElements()) {
String strKey = (String) enum1.nextElement();
String strValue = pps.getProperty(strKey);
System.out.println(strKey + "=" + strValue);
//封装到JavaBean。
}
}
}
```
### 读取规则
将配置文件中的值引入到java程序中。
将配置文件中的值引入到java程序中。
在Spring应用程序的environment中读取属性的时候每个属性的唯一名称符合如下规则
@@ -255,7 +279,9 @@ java -jar xxx.jar --server.port=8888
this.environment.containsProperty("spring.jpa.database-platform")
```
### 引入依赖
### 配置提示
引入配置提示的依赖。并在maven插件中将该依赖排除。
```xml
<dependency>
@@ -283,37 +309,19 @@ this.environment.containsProperty("spring.jpa.database-platform")
</build>
```
### @Value
* 通过占位符的方式加载自定义的参数
```
@Component
public class Book {
@Value("${book.name}")
private String name;
@Value("${book.author}")
private String author;
// 省略getter和setter
}
```
* @Value支持的表达式格式
```
#{...}
${...}
```
### @ConfigurationProperties
### @ConfigurationProperties+Componet
1. 只有在容器中的组件才会有Springboot的强大功能。
2. 从配置文件中自动加载进行属性配置然后使用Componet注册
@EnableConfigurationProperties + @ConfigurationProperties
假设在propertes配置中有这样一个配置
```
com.didispace.foo=bar
```
我们为它创建对应的配置类:
```
@Data
```java
@Component
@ConfigurationProperties(prefix = "com.didispace")
public class FooProperties {
@@ -336,4 +344,50 @@ public class Application {
System.out.println(foo.getFoo());
}
}
```
```
### @Configuration+ @EnableConfigurationProperties
1. 在配置类上开启属性配置功能。开启car的属性配置功能
2. 该中方法对配置类进行修改然后装配。不需要修改类本身的代码。
```
@EnableConfigurationProperties(Car.class)
class MyConfig{
}
```
* 完成配置绑定的类。
```java
// @Component,当该类子啊依赖中的的时候无法加载该注解
@ConfigurationProperties(prefix = "com.didispace")
public class FooProperties {
private String foo;
}
```
### @Value
* 通过占位符的方式加载自定义的参数
```
@Component
public class Book {
@Value("${book.name}")
private String name;
@Value("${book.author}")
private String author;
// 省略getter和setter
}
```
* @Value支持的表达式格式
```
#{...}
${...}
```

View File

@@ -0,0 +1,75 @@
## 1 springboot的启动过程
springcontext.run到底干了什么
```plantuml
@startuml
' 定义对象第一个对象SpringApplication是Springboot提供的第一个对象公民。
class SpringApplication{
run:通过静态的run方法创建第一个对象SpringApplication然后执行对象的run方法。
getRunListeners:通过Thread.concurrentThread.getContextClassLoader方法得到主线程当前线程的类加载器用于加载字节码文件
preapareEnviroment:准备属性配置文件。
}
@enduml
```
* SpringApplication.run该run方法可以启动一个类也可以启动多个类
```
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param primarySources the primary sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
```
## 2 自动配置加载的过程
### 加载过程
* @SpringBootConfiguration,就是一个@Configuration配置类。定义这是一个配置类。
* @ComponentScan指定包扫描
* @EnableAutoConfiguration
* @AutoConfigurationPackage自动配置包。将该包下的所有配置类导入进去。
* @Import(AutoConfigurationImportSelect.class)导入一个包。在autoconfiguration.jar包下META_INF/spring.factories文件中给出了全类名。
### 自动配置总结
* Spring 加载所有的自动配置类
* 每个自动配置类按照条件生效默认会绑定配置文件指定的值。xxxProperties和属性配置文件进行绑定。
* 生效的配置类给容器中装配很多组件。
* 只要容器中有这些组件,相当于这些功能就有了
* 只要用户配置了,以用户的优先。
* 定制化用自己的Bean替换底层的组件
* 用户去看这个组件获取的配置文件是什么值就去修改什么值。
### 需要怎么使用
1. 引入场景依赖
1. 看一下springboot官网的常见的starter场景
2. 查看自动配置了哪些类
1. 自己分析,引入场景对应的自动配置类,自动配置一般都生效了。
2. 配置文件中debug=true开启自动配置报告negative\postive会显示生效和不生效的配置
3. 是否需要修改
1. 参照文档修改配置项Properties配置绑定。参考官方的配置文档。
2. 自定义或加入替换组件。通过@Bean替换组件
3. 额外的自定义器。xxxCustomizer

View File

@@ -0,0 +1,58 @@
# web开发
将springboot和springmvc结合起来的讲解
关于父类和子类的作用的说明。记得在写毕设的时候自己把父类当做工具类子类在调用很多方法的时候为了少写代码就直接调用父类中的方法然后导致父类中的流程函数会调用子类中的方法子类中的函数又会调用父类中的方法非常凌乱两个类相互冗余。当时也在思考这些工具函数写在父类中供所有的子类调用与写一个util类有什么区别
现在发现,应该遵循一些默认的编码规则,父类用来构建整体的流程,而子类用来完善丰富一些子流程。相当于父类在构建主流程的时候,空出一些细节实现的部分,让子类来完善。而不是写一写类似的工具函数,让子类来调用,子类能够看到更加全面丰富的流程,那么父类就没有存在的必要了,父类的作用可能就是一个接口了,只提供一些对外的方法声明。
综上所属:
* 接口:只提供对外的方法声明
* 父类:提供完整的流程,由父类调用未经实现的抽象方法完成整体流程的构建。
* 子类:提供丰富的细节实现,由子类实现抽象方法的细节。
* 工具类:提供给所有子类的通用的处理函数。
## Springmvc的研究对象
```plantuml
@startuml
object HttpServlet{
doGet()
doPost()
doPut()
doDelete()
}
note bottom : 这是所有http请求的入口。\
\n 可以通过子类,不断丰富和具体要执行的内容。
object HttpServletBean{
}
object FrameworkServlet{
doGet()--> processRequest()
doPost()--> processRequest()
doPut()--> processRequest()
doDelete() --> processRequest()
processRequest()-->doService()
}
object DispatcherServlet{
doService()-->doDispatcher()
doDispatcher()
}
FrameworkServlet -|> HttpServlet : 重写do方法全部调用\nprocessRequest->doService
FrameworkServlet -> DispatcherServlet : 重写doService方法\n调用doDispatch进行处理
@enduml
```

View File

@@ -1,53 +0,0 @@
## Springboot注解
### @Autowired
@Autowired顾名思义就是自动装配其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。当然getter看个人需求如果私有属性需要对外提供的话应当予以保留。@Autowired默认按类型匹配的方式在容器查找匹配的Bean当有且仅有一个匹配的Bean时Spring将其注入@Autowired标注的变量中。这里@Autowired注解的意思就是当Spring发现@Autowired注解时将自动在代码上下文中找到和其匹配默认是类型匹配的Bean并自动注入到相应的地方去
### @Controller
修饰class用来创建处理http请求的对象.用于标注控制层组件(如struts中的action)
### @RestController
Spring4之后加入的注解原来在@Controller中返回json需要@ResponseBody来配合
### @ResponseBody
默认返回json格式
### @RequestMapping配置url映射。现在更多的也会直接用以Http Method直接关联的映射注解来定义比如GetMapping、PostMapping、DeleteMapping、PutMapping等
### @Service
服务层组件,用于标注业务层组件,表示定义一个bean自动根据bean的类名实例化一个首写字母为小写的bean例如Chinese实例化为chinese如果需要自己改名字则:@Service("你自己改的bean名")。
### @Repository
持久层组件用于标注数据访问组件即DAO组件
### @Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
## MyBatis注解
## Lombok注解
@Data 注解在类上;提供类所有属性的 getting 和 setting 方法此外还提供了equals、canEqual、hashCode、toString 方法
@Setter :注解在属性上;为属性提供 setting 方法
@Setter :注解在属性上;为属性提供 getting 方法
@ToString注解为使用该注解的类生成一个toString方法默认的toString格式为ClassName(fieldName= fieleValue ,fieldName1=fieleValue)。
@Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象
@NoArgsConstructor :注解在类上;为类提供一个无参的构造方法
@AllArgsConstructor :注解在类上;为类提供一个全参的构造方法
@RequiredArgsConstructor : 生成一个包含 "特定参数" 的构造器,特定参数指的是那些有加上 final 修饰词的变量们
@EqualsAndHashCode:自动生成 equals(Object other) 和 hashcode() 方法,包括所有非静态变量和非 transient 的变量。如果某些变量不想要加进判断,可以透过 exclude 排除,也可以使用 of 指定某些字段
@Cleanup : 可以关闭流
@Builder 被注解的类加个构造者模式
@Synchronized 加个同步锁
@SneakyThrows : 等同于try/catch 捕获异常
@NonNull : 如果给参数加个这个注解 参数为null会抛出空指针异常
@Value : 注解和@Data类似区别在于它会把所有成员变量默认定义为private final修饰并且不会生成set方法。

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB