diff --git a/Java三方库/commons-logging.md b/Java三方库/commons-logging.md new file mode 100644 index 00000000..e69de29b diff --git a/Java三方库/image/2022-11-15-14-38-18.png b/Java三方库/image/2022-11-15-14-38-18.png new file mode 100644 index 00000000..a1f13313 Binary files /dev/null and b/Java三方库/image/2022-11-15-14-38-18.png differ diff --git a/Java三方库/log4j.md b/Java三方库/log4j.md new file mode 100644 index 00000000..096d3775 --- /dev/null +++ b/Java三方库/log4j.md @@ -0,0 +1,306 @@ +https://blog.csdn.net/qq_43842093/article/details/122810961 + +### appender + +* ConsoleAppender: 日志输出到控制台; FileAppender:输出到文件; +* RollingFileAppender:输出到文件,文件达到一定阈值时,自动备份日志文件; +* DailyRollingFileAppender:可定期备份日志文件,默认一天一个文件,也可设置为每分钟一个、每小时一个; +* WriterAppender:可自定义日志输出位置。 + + + +### 日志级别 + +一般日志级别包括:ALL,DEBUG, INFO, WARN, ERROR,FATAL,OFF + +### 输出格式 + +1. org.apache.log4j.HTMLLayout(以HTML表格形式布局), +2. org.apache.log4j.PatternLayout(可以灵活地指定布局模式), +3. org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串), +4. org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) + +``` +-X号: X信息输出时左对齐; +%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL, +%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 +%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配置文件实例 +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + +### properties配置文件 + + +* 配置根Logger,Log4j建议只使用四个级别,优 先级从高到低分别是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 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL +%r 输出自应用启动到输出该log信息耗费的毫秒数 +%c 输出所属的类目,通常就是所在类的全名 +%t 输出产生该日志事件的线程名 +%n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n” +%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 +%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 ) ; +``` diff --git a/Java三方库/slf4j.md b/Java三方库/slf4j.md new file mode 100644 index 00000000..11e98201 --- /dev/null +++ b/Java三方库/slf4j.md @@ -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类用来获取Logger;slf4j-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; + } +``` \ No newline at end of file diff --git a/Java基础教程/Java语言基础/13 lambda表达式.md b/Java基础教程/Java语言基础/13 lambda表达式.md index e6e50dfe..7f0a8474 100644 --- a/Java基础教程/Java语言基础/13 lambda表达式.md +++ b/Java基础教程/Java语言基础/13 lambda表达式.md @@ -384,4 +384,27 @@ public static void main(String[] args) { //法二:(用Lambda) map.forEach((key,value)-> System.out.println("key:"+key+"value:"+value)); } -``` \ No newline at end of file +``` + + +## 5 jdk中的函数式接口 + +```java +@FunctionalInterface +public interface Runnable { + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see java.lang.Thread#run() + */ + public abstract void run(); +} +``` + +jdk中任意地方可以接收该接口的对象。是一个标准的无参、无返回值的函数。传入任何无参无返回值的函数即可执行。 \ No newline at end of file diff --git a/MyBatis/2XML配置.md b/MyBatis/2XML配置.md index e69de29b..4924a39a 100644 --- a/MyBatis/2XML配置.md +++ b/MyBatis/2XML配置.md @@ -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类型,多数情况直接用一般类型即可,比如 ​NULL​、​VARCHAR ​或 ​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 ​的时候是否调用映射对象的 ​setter​(map 对象时为 ​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的配置文件中配置多个数据源,然后分别进行事务的配置,如下所示: + + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + +### 配置数据源——主从数据源 \ No newline at end of file diff --git a/Spring/Springboot/01 内容简介.md b/Spring/Springboot/01 内容简介.md index 51f94bde..7f35e7b1 100644 --- a/Spring/Springboot/01 内容简介.md +++ b/Spring/Springboot/01 内容简介.md @@ -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 - - - nexus-aliyun - central - Nexus aliyun - http://maven.aliyun.com/nexus/content/groups/public - - - - - - jdk-1.8 - - true - 1.8 - - - 1.8 - 1.8 - 1.8 - - - -``` - - -### 创建maven工程 - -``` -mvn archetype:generate -``` - -### 引入依赖 - -``` - - org.springframework.boot - spring-boot-starter-parent - 2.3.4.RELEASE - - - - - - org.springframework.boot - spring-boot-starter-web - - - -``` - -### 创建主程序 - -```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 - - - - org.springframework.boot - spring-boot-maven-plugin - - - -``` - - -## 4 工程结构 - -### 推荐工程结构 -``` -com - +- example - +- myproject - +- Application.java - | - +- domain - | +- Customer.java - | +- CustomerRepository.java - | - +- service - | +- CustomerService.java - | - +- web - | +- CustomerController.java - | -``` -* root package:com.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 依赖管理 @@ -262,5 +87,43 @@ public class Bootstrap { 2.3.4.RELEASE -几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制 -``` \ No newline at end of file +``` + +### 自动配置 +> 通过java代码的方式,配置好其他组件。它在自动配置领域主要做了以下事情: +> * 默认的自动配置。对于所有组件,都指定了默认的约定俗称的最优的自动配置,用户可以不了解具体的配置项,开箱即用,按照约定完成业务逻辑即可。 +> * 可控的自动配置。对于所有组件,都提供了开放的自动配置接口,xxxProperties中读取并加载用户的配置属性,灵活地集成各种框架,高效快速定制化。 +> * 自定义自动配置。对于用户自定义的模块和组件,springboot提供了一套自动配置的解决方案,通过springboot的自动配置注解,完成用户自己的模块的自动配置。十分方便。 +> 从初阶的默认配置使用,通过配置文件定制化使用,借用springboot实现第三方模块自动配置的机制实现自定义模块自动配置,总共包括三个层次和阶段。 + + +例如:能够自动引入并配置好tomcat + +```xml + + org.springframework.boot + spring-boot-starter-tomcat + 2.3.4.RELEASE + compile + +``` + +* 自动引入并配置好SpringMVC,引入SpringMVC的组件 +* 自动配置好web常见的功能 +* 默认的包结构(配置好了默认的扫描路径) + +```java +@SpringBootApplication +等同于 +@SpringBootConfiguration +@EnableAutoConfiguration +@ComponentScan("com.atguigu.boot") +``` + +* 各种配置拥有默认值 + * 默认配置最终都是映射到某个类上,如:MultipartProperties + * 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象 +* 按需加载所有自动配置项 + * 非常多的starter + * 引入了哪些场景这个场景的自动配置才会开启 + * SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面 diff --git a/Spring/Springboot/02 创建项目.md b/Spring/Springboot/02 创建项目.md index 01de0e8a..162390dc 100644 --- a/Spring/Springboot/02 创建项目.md +++ b/Spring/Springboot/02 创建项目.md @@ -1,28 +1,62 @@ -## 1 创建一个springboot项目 +## 1 创建项目 -1. 创建Maven工程 -2. 引入依赖pom.xml - 1. 包括``下是springboot的标签。`dependencies`下是相关的依赖。 +### maven设置 +* 配置maven的Aliyun镜像和jdk版本 +```xml + + + nexus-aliyun + central + Nexus aliyun + http://maven.aliyun.com/nexus/content/groups/public + + + + + + jdk-1.8 + + true + 1.8 + + + 1.8 + 1.8 + 1.8 + + + +``` + + +### 创建maven工程 + +``` +mvn archetype:generate +``` + +### 引入依赖 ``` + org.springframework.boot + spring-boot-starter-parent + 2.3.4.RELEASE + + + + + org.springframework.boot - spring-boot-starter-parent - 2.3.4.RELEASE - + spring-boot-starter-web + - - - - org.springframework.boot - spring-boot-starter-web - - - + ``` -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 - - - org.springframework.boot - spring-boot-maven-plugin - - - + + + org.springframework.boot + spring-boot-maven-plugin + + + ``` ## 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 package:com.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 + + org.springframework.boot + spring-boot-starter-parent + 2.3.4.RELEASE + +``` 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方法。 \ No newline at end of file diff --git a/Spring/Springboot/03 Bean配置文件.md b/Spring/Springboot/03 Bean配置文件.md new file mode 100644 index 00000000..4dd88595 --- /dev/null +++ b/Spring/Springboot/03 Bean配置文件.md @@ -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. full(proxyBeanMehtods=true) + 2. lite(proxyBeanMethods=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========================= + + + + + + + + + + + + +``` + + +```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); + + + } +``` \ No newline at end of file diff --git a/Spring/Springboot/04 基本注解.md b/Spring/Springboot/04 基本注解.md deleted file mode 100644 index b926eb38..00000000 --- a/Spring/Springboot/04 基本注解.md +++ /dev/null @@ -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方法。可以解决组件间的依赖问题。如果为false,Springboot不会检查配置类中组件间的依赖,对于依赖的其他对象直接创建新的对象。true的时候每次运行都会检查配置中组件间的依赖,不会创建新的对象。 - 1. full(proxyBeanMehtods=true) - 2. lite(proxyBeanMethods=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. 容器中的自动注入。 - \ No newline at end of file diff --git a/Spring/Springboot/03 配置文件.md b/Spring/Springboot/04 属性配置文件.md similarity index 81% rename from Spring/Springboot/03 配置文件.md rename to Spring/Springboot/04 属性配置文件.md index e70f4cc4..b0d525aa 100644 --- a/Spring/Springboot/03 配置文件.md +++ b/Spring/Springboot/04 属性配置文件.md @@ -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 @@ -283,37 +309,19 @@ this.environment.containsProperty("spring.jpa.database-platform") ``` -### @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()); } } -``` \ No newline at end of file +``` + + +### @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支持的表达式格式 +``` +#{...} +${...} +``` diff --git a/Spring/Springboot/05 自动配置原理.md b/Spring/Springboot/05 自动配置原理.md new file mode 100644 index 00000000..b63fbb26 --- /dev/null +++ b/Spring/Springboot/05 自动配置原理.md @@ -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 + + + + diff --git a/Spring/Springboot/06 web开发.md b/Spring/Springboot/06 web开发.md new file mode 100644 index 00000000..14ea986a --- /dev/null +++ b/Spring/Springboot/06 web开发.md @@ -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 +``` \ No newline at end of file diff --git a/Spring/Springboot/4注解详解.md b/Spring/Springboot/4注解详解.md deleted file mode 100644 index 53eeb906..00000000 --- a/Spring/Springboot/4注解详解.md +++ /dev/null @@ -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方法。 - - diff --git a/Spring/Springboot/image/2022-11-17-09-35-48.png b/Spring/Springboot/image/2022-11-17-09-35-48.png new file mode 100644 index 00000000..a7f5b90d Binary files /dev/null and b/Spring/Springboot/image/2022-11-17-09-35-48.png differ diff --git a/Spring/Springboot/image/2022-11-18-09-53-55.png b/Spring/Springboot/image/2022-11-18-09-53-55.png new file mode 100644 index 00000000..1ebc7421 Binary files /dev/null and b/Spring/Springboot/image/2022-11-18-09-53-55.png differ