JavaEE进阶2.0
目录一、 spring core1.0 Ioc简介(1)Ioc简介(2)Ioc的引入(3)spring IoC和DI2.0 详解Ioc(1)Bean简介(2)Bean name规则(3)三种不同语义的Bean获取方式(4)注解3.0 DI(1)DI简介(2)依赖注入的方式(3)Autowired存在的问题(4)Ioc和DI总结4.0 常见面试题(1)Autowired 和 Resource的区别(2)Spring SpringBoot 和 Spring mvc的关系以及区别二、SpringBoot配置文件1.0 简介(1)配置文件(2)配置文件说明 properties(3)配置文件说明 yml /yaml三、验证码案例1.0 验证码案例(1)简介(2)需求2.0 问题(1) 静态内部类(2)session四、spring日志1.0 简介(1)为什么学习日志(2)日志的作用(3)springboot的日志(4)日志级别(5)日志持久化(6)日志文件分割(7)配置日志格式(8) 更简单的日志输出一、 spring core1.0 Ioc简介(1)Ioc简介spring最原始的样子是什么样的spring corespring core是spring的核心模块 长下面这一个spring是一个包含众多工具的IoC容器 容器是一个抽象的概念 可以装很多东西IoC控制反转解释反转 字面意思 反差 控制字面意思 控制权 对象的控制权发生了发转之前对象的控制权在之前是谁使用在谁手上 之前是需要你手动创建对象现在是spring控制 对象由spring帮你创建和注入(2)Ioc的引入传统程序开发的流程 以造一辆车为例来了解一下IoC如果这个时候需求发生变化呢例如 我希望的是用户说轮胎多少尺寸然后得到多少相应尺寸的车子相应的函数里面要设置好参数 都改为这样传统方式的问题:一个函数改了代码参数 其他函数都得跟着改当客户提出的五花八门的需求时按照这种方式 改来改去 效率非常的低Ioc的方式也就是外包的思想 具体的实现代码是这样的改变创建car的时候 不自己new了 外包给framework framwork就是从外包公司拿过来的 最后造汽车只是组装一下各个零件之后要增加新的需求 例如增添轮胎的颜色 就从轮胎里面加上新的代码就可以了而不需要修改所有的代码 这样就是实现了解耦上述的外包公司 我们在这里可以类比为spring 对象的控制权交给了spring创建对象的过程叫做Ioc 拿来用的过程叫做注入DI(3)spring IoC和DIcomponent表示是由spring来创建 管理它的对象(实例)spring启动时会自动扫描这个类创建它的对象并保存你需要用的时候直接拿就行 不用手动创建Autowired表示从spring当中获得对象 并给属性赋值从spring容器中获取BookDao这个类型的对象 并赋值给bookDaocompoent和autowired对应一个表示是存 一个表示是取2.0 详解Ioc(1)Bean简介BeanBean是spring容器(IOC容器)所管理的一个Java对象它由spring创建 装配 初始化 生命周期管理以及销毁 简单来说不是你new出来的 是Spring给你造好 配好 管理好的对象Bean的存储注解实现Bean的存储指的是通过在类、方法或者字段上添加特的Spring注解 将该类或对象自动注册为Spring容器管理的BeanApplication 应用 Context 上下文//表示一个容器例如ApplicationContext 表示应用的上下文 可以表示Spring的运行环境(2)Bean name规则Bean name:bean是spring容器创建 管理 装配的对象 而Bean name就是spring给这个对象在容器中起的唯一标识符HelloController----helloController BookDao----bookDaoUSCcontroller---USCcontroller注意当前两个字母是大写的时候 类名和对象名是一致的也可以直接指定 不用默认的getBean从spring容器中主动获取一个由spring创建兵管理的Bean实例(3)三种不同语义的Bean获取方式HelloController bean1 context.getBean(HelloController.class)//适合该对象类型只有一个 返回的是ObjectHelloController bean2 (HelloController) context.getBean(helloController) 注意强制转换//需要精确通过Bean的名称获取 切不关心类型(或者类型在编译期间不可知)HelloController bean3 context.getBean(helloController,HelloController.class)//需要按照名称精准定位Bean 要求编译器类型安全运行时类型校验//认识错误日志先看异常是什么 //控制台输出的就是错误日志(4)注解Controller注解上下文可以理解为容器 就是存东西的 表示前后的一种关系 绵绵潺潺的service注解 Repository注解 Component注解 Configuration注解这五个注解就是用来告诉spring管理对象 标了这五个注解 就会告诉spring创建一个对象放到里面那么这五个注解有什么区别呢其他四个都是Component的衍生注解 那为什么要区分 不同的含义晋A 晋B 晋CController 控制层 Service 业务逻辑层 Repository 数据层 configuration 配置层componet组件层 //实际应用过程中这5个注解的边界并没有那么清晰Controller不可以和其他注解替换控制层必须使用Controller其他几个注解可以替换 但是不建议 因为不同的注解表示的含义不同 可能造成不必要的麻烦Bean注解方法前面加Bean之前 类上要加五大注解//Bean要配合五大注解使用Bean name默认为方法名 Bean可以重命名 name和value是一样的 value又可以省略Bean在哪些场景使用扫描路径spring的扫描路径默认是启动类所在的路径及其子路径 //看源码就可以发现但是加了ComponentScan之后 就以componentscan括号里面的路径为扫描路径了所以一般把启动类放在最外层可以通过ComponentScan来定义扫描的路径 ComponentScan (com.bit.ioc.component)3.0 DI(1)DI简介Dependecy Injection依赖注入图片化的理解什么是依赖 例如BookController需要正常工作 需要有bookService bookService需要正常工作 需要里面有bookDaoBookController依赖bookService bookDao依赖bookService 可以理解为里面的一些属性依赖的核心是A 类的功能实现离不开 B 类的协助A 就依赖 B。DI 表示依赖注入如何从spring中取到对象 并且赋值给它你只要告诉spring容器 我需要xx对象 它就把xx对象直接送到你的手上(2)依赖注入的方式1.属性注入Autowiredprivate UserService userService在后面的代码里面就可以调用userService的方法 实现了依赖的注入过程Autowired注解 在spring容器中根据类型获取对象并赋值Autowired帮助实现 spring看到Autowired注解 知道你要给userService属性赋值spring去自己的容器里面找userService属性类型的beanspring把找到的UserService对象赋值给userService属性DI测试 HelloController bean context.getBean(HelloController.class); 打印结果是既有do Controller又有do Service在调用Controller的时候 userService方法也执行了//context是spring的Ioc容器 *仓库下面是有关的两个报错信息 错误日志是一段一段的 从下面往上面倒着看缺陷bean 一个类型是可以有多个对象 当有多个对象 autowired注入的时候就是失败了2.构造方法注入private UserService userService public HelloController(UserService userService) { this.userService userService; }如果只有一个构造方法 Autowired可以省略如果有存在多个构造方法spring帮我们管理对象的时候 默认调用的是无参的构造函数也可以通过Autowired来指定默认的构造方法//如果想要证明的话 自己可以测试 然后看错误日志 没得选的时候选唯一的 多选一的时候报错3.setter方法注入也需要加上Autowired注解Autowiredpublic void serUserService (UserService) { this.userService userService }//多个的话 得分别标记上Autowired一个Autowierd只对下面一行起作用多个的时候一定要多Autowired4.三种方式优缺点分析属性注入 优 简洁方便 缺 只能在spring中使用 不能修饰final属性 private final UserService错误解释final 必须在对象创建完成前完成初始化且初始化后不可修改。 //因为是类加载这样就只能两种方式声明时直接赋值 private final UserUservice us newUserService( );//我们写Autowired就是为了自动注入 现在自己new了 那加注解的意义何在在类的构造方法中赋值 private final UserService uspublic HelloController (UserService us) { this.us us; } 在构造器中完成初始化spring属性注入 实际发生在对象创建之后构造函数注入(spring 4.x推荐) 优 可以注入final修饰的属性注入的对象不会被修改 //没办法赋值了通用性好(构造方法是JDK支持的)依赖对象在使用前一定会被完全初始化 构造方法在类加载阶段就会执行缺 注入多个对象时 代码会比较繁琐setter注入(spring 3.x推荐) 优 方便在创建对象之后 重新对该对象进行配置或者注入缺 不能注入一个final修饰的属性注入对象可能会被改变 因为setter方法可能会被多次调用 就有被修改的风险(3)Autowired存在的问题当同一个类型有多个对象要怎么办 因为Autowired是根据类型对应的 就会存在这样的情况解决方式 idea编译器会有报错信息//最下面一行 说了两个解决方式 圈主的那个一种是加注解Primary 来标明哪个是主要的另一种是加注解Qualifier qualifier 修饰符 限定符 限定词 Qualifier(s3) 限定了用s3另另一种是加注解Resource Resource(s3)// 告诉 Spring“我要从容器 里找一个指定的‘资源Bean’并注入到这个属性里” 就不用写Autowired注解了一般用另一种和另另一种 比较简便//Qualifer注解的另一种用法 这个就是用来指定名称的 可以加在属性上 也可以加在参数上Beanpublic Student s2 ( Qualifier(name2) String n ) 这样也可以区分依赖注入 通常使用Autowired和Resource 对于参数通常使用Qualifier(4)Ioc和DI总结context是spring的应用环境 是springIoc容器beanFactory和Application的区别获取bean对象是父类BeanFactory提供的功能 它有基础的访问容器的能力ApplicationContext属于BeanFactory的子类它除了继承了BeanFactory的所有功能外还参加了对国际化支持资源访问支持以及事件传播等方面的支持性能方面ApplicationContext是一次性加载并初始化所有的Bean对象而BeanFactory是需要哪个就去加载哪个 更加的轻量化(空间换时间)4.0 常见面试题(1)Autowired 和 Resource的区别Autowired 是spring提供的注解 Resource是jdk提供的注解Autowired 是依照类型注入 而Resource是按照名称注入的 Resource支持更多的参数设置(2)Spring SpringBoot 和 Spring mvc的关系以及区别spring是框架 简化企业级应用程序的开发主要功能是管理对象 以及对象之间的依赖关系 //面向切面编程 数据库事务管理 web框架支持这个图片就是spring的部分 包含了Ioc和DIspringbootspringboot是对spring的一个封装 为了简化spring应用而开发出来的中小型企业 没有成本研究自己的框架springboot可以更加快速的搭建框架 降级开发成本 让开发人员更加专注于spring应用的开发而无需关注一些xml配置和底层的实现是基于spring进行开发spring类似于火车 高铁spring boot类似于12306 功能不局限于火车 引入一些第三方的工具 例如集成了tomcat 等spring mvc是spring的一个子框架 spring诞生之后 大家觉得很好用 于是按照mvc模式设置了一个mvc框架主要用于开发web应用 和 网络接口类似于火车站车票待售点//以大楼为例子 也可以把spring理解为核心地基 钢筋结构 springboot为脚手架 springmvc是大楼门面和外部接待系统(3)三种注入方式的优缺点上面的第四点(4)常见的注解有哪些 分别是什么作用?ediayr笔记上面二、SpringBoot配置文件1.0 简介(1)配置文件电脑的配置文件 maven配置文件 ....... 配置文件一直在使用配置文件的作用配置文件主要是为了解决硬编码带来的问题 把可能会发生改变的信息 放在一个集中的地方当我们启动某个程序时 应用程序从配置文件中读取数据 并加载运行硬编码代码写死 例如每次打开某个软件 字数大小都是那样 但是不同的用户有不同的喜好我们就可以把手机字体的大小放在配置文件中当程序启动时读取配置以用户设置的字体大小来显示。springboot的配置文件 项目的启动端口 数据库的连接信息 第三方系统调用密钥等信息(2)配置文件说明 properties三种格式Properties yml yaml--yml是yaml的简写默认的配置文件 application.properties 可以手动指定如果同时存在properties和yml两个配置文件 两个文件同时生效如果yml文件和properties设置内容冲突时 以properties为准properties基本语法是以键值对的形式配置的 key和value之间是以 连接的 所有单词小写 单词之间用.分割例: spring.datasource.username rootproperties的注释是一个## 配置数据库连接信息Value注解 把配置文件里面写好的配置值直接 抓 到代码里面 不用在代码里硬写死Value( {my.key } ) private String myKey ;例PostConstruct注解 初始化方法public vodi init sout ( mykey29mykey2)spring创建完成某个bena 并把所有的属性(比如Value注入的mykey)都赋值完成之后 会自动执行这个注解标记的方法 而且只执行一次properties缺点分析properties配置文件中会有何怒都冗余的信息 例如好几个开头都是spring.datasource如何解决乱码问题改两个地方file settings表示改的是当前项目 搜索encoding能看到都改为utf-8之前乱码的恢复不了了 但是之后不会出现乱码的问题了new project setup(创建新项目的时候)点开之后还是那个页面 还是都修改成utf-8(3)配置文件说明 yml /yamlyml基本语法yml的格式比较复杂 容易发生错误空格不可以省略 port前面也有相当于porperties .换为空格当有共同前缀的时候例对齐的地方表示属于一级(类似于文件系统) url和username和password上一级是datasource datasource的上一级是spring自定义key理解如果是string格式 就是那个hello 而且这个hello是可以自己更改的null是关键字 不可以把null放到配置文件里面 会报错~表示null值 它相当于Java中的null 如果某个配置项没有值 可以显式写成~来表示空读取简单解释一下代码 Controller注解 让spring管理 自动创建对象PostConstruct自动初始化方法 这两个注解结合起来实现配置对象ConfigurationPropertiesprefix 注解把配置文件(yml/properties)里所有以person为前缀的配置项 一次性抄写到当前类的属性里 不用像Value那样挨个读配置集合//类的生命周期实例化 依赖注入 初始化方法 使用 销毁配置Map配置集合 配置map等 要放在对象里面spring读不了孤立的集合/map 集合/map是归属某个对象的属性例如公告栏上面只贴打球 跑步 看书 音乐(孤立的集合) 别人看到会问”这是谁的爱好”你必须贴好 这个是张三的爱好 把集合/map归类到张三这个对象下面yml优缺点优点可读性高 写法简单 易于理解支持更多的数据类型 可以简单表达对象 数据 list map等数据形态支持更多的编程语言 不止是Java中可以使用 在golang python ruby javaScrpit中也可以使用缺点: 不适合写复杂的配置文件 不适合写稀疏的文件对于格式有比较强的要求 一个空格可能会引发一场血案三、验证码案例1.0 验证码案例(1)简介//贴这个图片单纯无聊 感觉好看哈哈验证码的实现方式很多 可以前端实现 也可以后端实现网络上也有比较多的工具包 之前验证码是为了区分人与机器的 仙现在机器也能操作验证码了很多厂商开始和电话合作 发送那种短信的验证码 (需要付费)效果展示图(2)需求如何实现验证码随机字符串干扰元素字符串可以来个数字集 字符集 汉字集等 放在一个数组里面 干扰元素可以是横线 可以是曲线一张图片 里面放那个字符集 随机两个点 生成一些线段 贴上字符滑动拼图验证码 只要是有个图片集 叠加 拿到坐标传递给后端 后端对比坐标准备工作hutool工具 简介 | Hutool在hutool上面 看不懂介绍 看不懂代码 先复制下来 放到ieda项目的test模块中 或者自己创建一个项目试一试引入依赖 设置好版本号 在测试类里面尝试定义接口1.返回验证码 后端返回一个验证码请求URL cpatcha / getCaptcha响应验证码图片内容2.校验 验证码是否正确请求URL cpatcha/check 请求参数captchaxn8d响应true false优化把图片验证码的大小放到配置文件中http是无状态的 为了保存用户的信息 采用的是session和cookie写response写到最上面2.0 问题(1) 静态内部类静态内部类可以独立存在 而实例内部类必须依附于外部类的对象假如我们要设计一个Person类每个人都有一张身份证身份证属于这个人但是身份证本身就是一个独立的概念 不需要访问其他人的属性(2)session验证码的session的key写死了 那么多个用户请求验证码的时候是不是会有错 //并发的情况知识准备session 存储用户信息的会话机制 之前也记录过 这个session像是图书馆的借阅记录 就是后端的记录机制 cookie是后端和前端沟通的桥梁cookie是后端发给前端的cookie通常不会直接存储session的数据 而是存储一个唯一标识符(Session ID) 因为HTTP是无状态的嘛 每次发送请求的时候 cookie会自动附带在HTTP的头部发送给服务器当用户第一次访问服务器的时候服务器会生成一个Session 并创建一个对应的Session ID服务器通过Set-Cookie响应头 将这个Session ID发送给浏览器 浏览器将其保存为Cookie后续每次请求浏览器会自动在Cookie中带上这个SessionID 服务器根据接收到的Seesion ID 在内存或者数据库查找对应的Session数据 从而识别用户过程1用户1获取验证码后端获取的Session 为空会创建一个对象 //这个对象包含session ID 对应一个session对象 这个对象里面是key value结构2服务端进行返回 会把Seesion通过Set-Cookie返回3客户端接收到响应 发现header有set-Cookie 就会把信息存储在客户端4用户2发起请求 重复的上面的123步骤 此时得到如下结果//这里分别用chrome浏览器和edge浏览器模拟不同的客户端5用户1校验验证码 发送请求的时候 携带Cookie信息 Cookie里面的seesion ID信息获取到 sessiontomcat本身就是一个线程池 支持多线程 当请求来的时候这个请求从tomcat里面获取一个请求 下一个请求来的时候 再从tomcat里面获取一个请求 所以我们开发的时候 不用考虑多用户的场景 线程的安全性是服务器本身就保证了的总结多个用户请求验证码的时即使Seesion的Key写死也不会出错。因为每个用户有独立的Session对象 数据互不干扰 并发场景下服务器通过多线程和Session的隔离机制 保证了安全性例下面是我们一个客户端发起多次请求 客户端自动匹配的多线程模式 看日志我们就能看到这些记录四、spring日志1.0 简介(1)为什么学习日志之前使用的代码System.out.print来打印日志虽然感觉这个概念有点陌生 但是其实我们早已在不知不觉中用了好多次了比如前端页面 出现问题的时候 我们去按F12 在控制台找错误在第几行代码 这个就是一个日志比如程序突然崩溃 我们不会一行一行看代码哪里错了 而是去控制台看错误日志 这里错误日志就是日志的一部分..........随着项目复杂度的上升我们对打印的日志也有了更高的要求 而不仅仅是定位和排查问题比如需要记录一下用户的操作记录 也可能需要日志来记录用户的一些喜好 把日志持久化后续进行数据分析等 sout 不能很好的满足我们的需求 我们就需要使用一些专门的日志框架通俗的例子sout时代 你只能在开发时看”订单已经创建“”数据库连接成功 “ 关掉DEA就没有了专业的日志时代记录下每个用户的下单时间 点的菜品 口味偏好(数据持久化 存在服务器)运营人员月底分析日志发现80%的用户点微辣 于是推出”微辣套餐促销”如果某天气系统崩溃运维查看错误日志迅速定位到“数据库连接池满”并扩容(2)日志的作用除了之前的发现问题 分析问题 定位问题外 日志还有很多用途系统监控 监控每一个方法的运行时间 响应时间 运行点等等数据采集浏览量 访问量 排序浏览时长排名等 后续其他的算法人员 大模型人员根据这些数据分析用户喜好 然后做相关的喜好推荐日志审计网络安全越来越受到大家的关注 系统安全也成为一个重要的环节安全审计也是系统中非常中非常重要的部分 通过系统日志分析可以判断一些非法攻击 非法调用 以及系统处理过程中的安全隐患网络上面的任何行为都是有痕迹的(3)springboot的日志时间 日志级别 进程ID 应用名称 线程名称 类的路径 日志内容 .....类的路径这里有一套规范如何打印idea这样的日志呢spring内置的日志框架 org.slf4j日志框架(了解)四个日志框架 (上面图片勾住的红色的内容)区别是什么了解即可日志门面日志实现SLF4J通用遥控器 可以用很多 其他的三个是日志实现 日志实现可以单独使用充电线没有统一的时候 有很多种 现在的充电线统一好多了SLF4J框架Simple Looging Facade Java ---Java简单日志门面不引入日志门面有很多问题这里不在一一赘述引入日志门面框架之后应用程序和日志框架(框架的具体实现)之间有了统一的API接口此时应用程序只需要维护一套日志文件配置 SJF4J就是其他日志框架的门面SLF4J可以理解为是提供日志服务的统一API接口并不设计到具体的日志逻辑实现常见的日志框架有很多log4J logback等外观模式门面模式又称做外观模式 重思想轻代代码的实现有很多种提供了一个统一的接口 用来访问子系统的一群接口其主要特征是定义了一个高层接口 让子系统更容易调用门面模式的实现两种角色 门面角色 系统对外的统一接口子系统角色可以同时拥有一个或者多个子系统角色 每个子系统角色都不是一个单独的类而是一个类的子集合 子系统角色并不知道门面角色的存在 对于子系统而言门面角色只是另一个客户端而已场景进家开灯 出门关灯实现创建一个客户端Main 还有卧室类 厨房类 客厅类等等 这些子类都是实现light接口FacadeLight类 希望用这个类来关闭所有的灯 里面创建了卧室对象厨房对象灯 里面的重写方法都调用了每个房间的开灯 客户端Main开灯直接调用FacadeLight类的方法就可以了(4)日志级别为什么要有日志级别分类就像是老板想要管理公司 但是不能大大小小的事情都来找老板把级别FATAL ERROR WARN INFO DEBUG TRACE翻译单词 fatal 致命 error 错误 warn 警告 info (information)信息 debug 调试 trace 追踪如何打印不同级别的日志logger.inf0日志默认级别是info 低于info级别自动不打印但是这个默认级别也是可以调整的配置文件里面修改这里的root是根目录的意思哇咔咔 出来好多啊 满满的几屏幕 而且还在一直加 好多好多好多 哈哈哈 好玩如果想要对单独某个文件的日志修改 跟在下面(5)日志持久化引入: 重启了项目之后 之前的日志没有了 这个时候怎么办日志不存 出事抓瞎 日志存了 有据可查两种方式1配置日志文件名logging.file.name logger.springboot.log //yml格式就不演示了//写好之后 记得刷新一下file也可以配置路径 file : name: log/log.log2配置日志的存储目录logging.file.path这样直接存储到电脑的硬盘上面了 甚至可以logger/log.log 此时logger是一个文件夹优先级如果两种配置同时存在 以logging.file.name为主(6)日志文件分割日志是堆积的 长年累月 如果一个日志文件动不动几个G 容易打不开//这里如果可以规定 日志文件超过xxx可以分割默认的是超过10M也可以指定划分的文件的名称file-name-pattern:{LOG_FILE}.%d{yyyy-MM-dd}.%i.gz %d表示日期 yyyy-MM-dd表示日期的格式通常情况下 运维人员负责清理日志(7)配置日志格式%clr(表达式){ 颜色 } 设置输入日志的颜色%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-ddTHH:mm:ss.SSSXXX}} ⽇期和时间--精确到毫 秒%5p显⽰⽇志级别ERRORMARNINFODEBUGTRACE.%t线程名.%c类的全限定名.%Mmethod.%L为⾏号.%thread线程名称.%m或者%msg显⽰输出消息.%n换⾏符%5若字符⻓度⼩于5则右边⽤空格填充.%-5若字符⻓度⼩于5则左边⽤空格填充.%.15若字符⻓度超过15截去多余字符.%15.15若字符⻓度⼩于15则右边⽤空格填充. 若字符⻓度超过15截去多余字符(8) 更简单的日志输出lombook给我提供了一种更简单的方式使用slf4j注解输出日志过程添加lombok依赖 //这样实现了使用注解打印日志加上这个注解 自动生成log对象 我们直接使用就可以了 这种做法也是spring的特点---注解
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2425427.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!