02springboot自动配置&配置文件
三、自动配置
13、自动配置【源码分析】-自动包规则原理
Spring Boot应用的启动类:
12345678@SpringBootApplicationpublic class MainApplication { public static void main(String[] args) { SpringApplication.run(MainApplication.class, args); } }
分析下@SpringBootApplication
123456789101112131415161718@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class}), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class})})public @interface SpringBootApplication { ...}
重点分析
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
@SpringBootConfiguration
12345678910@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @interface SpringBootConfiguration { @AliasFor( annotation = Configuration.class ) boolean proxyBeanMethods() default true;} ...
程序员面试金典-java代码实现
程序员面试金典-java代码实现
由于全部题目保存在一个文件中会导致Markdown非常卡顿
程序员面试金典1~3 | dhx_'blog (adorabled4.github.io)
程序员面试金典4~5 | dhx_'blog (adorabled4.github.io)
程序员面试金典4~5
04树与图
⚠️面试题 04.01. 节点间通路
难度中等65
节点间通路。给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。
法一:
递归, 从target反向寻找路径,
注意不要直接return findWhetherExistsPath(n,graph,start,arr[0]);
因为可能有多个节点都能到达target , 而 能从start到 target 的却只有一个
注意点 :
这个方法无法解决自环的问题:
比如:
findWhetherExistsPath(6, new int[][]{{1,2},{2,3},{3,4},{4,5},{4,1}},5,1) 自环
但是题目给的数据没有涉及到自环的,
解决自环问题:
加一个visited数组即可
12345678910111213class Solution { public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) { if(start==target) return true; boolean res=false; for(int[] arr:graph){ if(arr[1]==target){ res= findWhetherExistsPath(n,graph,start,arr[0]); } if(res) return res; } return res; }}
解决自环问题:
法二: 明天再写
DFS
面试题 04.02. 最小高度树
难度简单135
给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树。
因为题目给的是一个升序数组,需要构建二叉搜索树,
当构造二叉搜索树的左右平衡时深度是最小。
如果想要左右平衡可以让根节点是排序数组的中点,这样左边有x个右边也约有x个,大致保持一致。
构造树一般采用的是前序遍历,
因为先构造中间节点,然后递归构造左子树和右子树。先要找到数组中中间值和对应的下标,
中间值构造根 ...
程序员面试金典1~3
01数组与字符串
面试题 01.01. 判定字符是否唯一
难度简单229
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
使用数组统计每个字符出现的个数, 如果有出现次数大于一次的, 说明有重复字符 , 也就是! 全都不同
123456789101112class Solution { public boolean isUnique(String astr) { int[]cnt=new int[26]; for (char c : astr.toCharArray()) { cnt[c-'a']++; } for (int i : cnt) { if(i>1) return false; } return true; }}
面试题 01.02. 判定是否互为字符重排
难度简单78
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
全部排序然后判断是否相同即可
123456789class Solution { public boolean CheckPermutation(String s1, String s2) { char[] chars1 = s1.toCharArray(); char[] chars2 = s2.toCharArray(); Arrays.sort(chars1); Arrays.sort(chars2); return Arrays.equals(chars1, chars2); }}
面试题 01.03. URL化
难度简单82
URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)
题目说的知道真实的长度, 大概的意思就是后面的有些空格是有效的, 所以本题如果直接trim(), 就WA 了
解法:
提前遍历, 获取空格的个数
遍历, 如果遇到空格, 就赋值%20
返回赋值的字 ...
队列
概述
队列(queue) 是一种 先进先出(FIFO) 的、操作受限的线性表
算法一看就懂之「 队列 」 - 知乎 (zhihu.com)
队列的 主要种类:
[顺序队列](# 1、顺序队列)
[链式队列](# 2、链式队列)
[循环队列](# 3、循环队列)
[优先队列](# 4、优先队列)
[双端队列](# 5、双端队列)
[单调队列](# 6、单调队列)
1、顺序队列
2、链式队列
3、循环队列
4、优先队列
优先队列 - 知乎 (zhihu.com)
5、双端队列
抛砖引玉 | 图解双端队列Deque - 知乎 (zhihu.com)
双端队列又名double ended queue,简称deque,双端队列没有队列和栈这样的限制级,它允许两端进行入队和出队操作,也就是说元素可以从队头出队和入队,也可以从队尾出队和入队。
1public interface Deque<E> extends Queue<E> {}
Deque是一个双端队列接口,继承自Queue接口,Deque的实现类是LinkedList、ArrayDeque、LinkedBlockingDeque,
其中LinkedList是最常用的。
Deque有三种用途:
普通队列(一端进另一端出):
Queue queue = new LinkedList()或Deque deque = new LinkedList()
双端队列(两端都可进出)
Deque deque = new LinkedList()
堆栈
Deque deque = new LinkedList()
注意:Java堆栈Stack类已经过时,Java官方推荐使用Deque替代Stack使用。Deque堆栈操作方法:push()、pop()、peek()。
此接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败。
第一个元素 (头部)
最后一个元素 (尾部)
抛出异常
特殊值
抛出异常
特殊值
插入
add ...
位运算
位运算
位运算概述
从现代计算机中所有的数据都以二进制的形式存储在设备中。即0、1两种状态,计算机对二进制进行的运算(+、-、*、/)
都叫位运算
位取反(~)
位取反即之前负数转二进制所用的方式,即0变1,1变0。
121000110001110011
位与(&)
位与即如果两个位进行比较两位同时为1,结果才为1,否则结果为0。
例如: 125 & 7
12345678910111213 125 & 7 二进制: 01111101 & 00000111 位与比较: 0 1 1 1 1 1 0 1---------------0 0 0 0 0 1 1 1| | | | | | | |× × × × × √ × √| | | | | | | |0 0 0 0 0 1 0 1 结果: 125&7 = 0000 0111 = 5
剑指 Offer 65. 不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
利用^ 以及&, 巧妙的进行相加
首先 ,我们有两个数字,
需要先获取 非进位的和 n (n= a^b)
然后获取进位的和 : p (p=a&b<<1)
然后我们 通过 n= n^p 就得到了和 ( 进位和 + 非进位和)
9 : 1001
26: 11010
n: 10011
p: 10000
n: 00011 , 可见, 如果仅仅是 n^p 可能存在新的进位的情况 ,
此时我们继续使用 p 来记录 n&p<<1 的结果 ,
p: 100000
这里需要用到一个新的数字(temp)来储存 n&p<<1 的结果, 因为如果先 异或再 & , 就会导致先相加, 再&, 相当于重复计算了
然后继续执行上一步类似的操作 也就是 n= n^p
n:100011 : 35 得到正确结果
123456789101112class Solution { public int add(int a, int b) { int n=a; int p=b; //存储上一轮的 进位和结果 while(p!= ...
SSM整合
四、SSM整合
4.1、ContextLoaderListener
Spring提供了监听器ContextLoaderListener,实现ServletContextListener接口,可监听ServletContext的状态,
在web服务器的启动,读取Spring的配置文件,创建Spring的IOC容器。web应用中必须在web.xml中配置
spring中的IOC容器无法访问springmvc的IOC容器,springmvc是子容器,可以访问spring的IOC容器(父容器)
12345678910111213<!-- 设置监听器--> <listener><!-- 在服务启动时,加载spring的配置文件 获取ioc 容器--> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener><!-- 由于 spring的配置文件默认在 WEB-INF下 ,但是我们习惯吧配置文件放在resources 目录,所有这里再重新配置一次--> <context-param><!--自定义Spring配置文件的位置和名称--> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param>配置Spring的监听器,在服务器启动时加载Spring的配置文件Spring配置文件默认位置和名称:/WEB-INF/applicationContext.xml可通过上下文参数自定义Spring配置文件的位置和名称
4.2、准备工作
1>创建Maven Module
2>添加web模块
3>导入依赖
pom.xml
12345678910111213141516171819202122232 ...
SpringMVC(5)注解配置springmvc&&springmvc执行流程
13、注解配置SpringMVC
使用配置类和注解代替web.xml和SpringMVC配置文件的功能
13.1、创建初始化类,代替web.xml
在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置Servlet容器。
Spring提供了这个接口的实现,名为SpringServletContainerInitializer,
这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。
Spring3.2引入了一个便利的WebApplicationInitializer基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer,当我们的类扩展了AbstractAnnotationConfigDispatcherServletInitializer并将其部署到Servlet3.0容器的时候,
容器会自动发现它,并用它来配置Servlet上下文。
WebInit.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445package pers.dhx_.config;import org.springframework.web.filter.CharacterEncodingFilter;import org.springframework.web.filter.HiddenHttpMethodFilter;import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;import javax.servlet.Filter;/** * @author Dhx_ * @className WebInit * @description TODO 代替 web.xml * @date 2022/7/29 9:37 */public class WebInit extends Abstrac ...
动态规划
动态规划
如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。
比如一些求最值的场景,如最长递增子序列、最小编辑距离、背包问题、凑零钱问题等等,都是动态规划的经典应用场景。
解题思路
动态规划的核心思想就是拆分子问题,记住过往,减少重复计算。 并且动态规划一般都是自底向上的,因此到这里,基于青蛙跳阶问题,我总结了一下我做
动态规划的思路:
穷举分析
确定边界
找出规律,确定最优子结构
写出状态转移方程
在很多教程中都会写,动态规划有两种计算顺序,一种是自顶向下的、使用备忘录的递归方法,一种是自底向上的、使用 dp 数组的循环方法。不过在普通的动态规划题目中,99% 的情况我们都不需要用到备忘录方法,所以我们最好坚持用自底向上的 dp 数组。
SpringMVC(4)文件相关
小知识:
如果controller中的方法 , 没有设置返回值,系统就默认将请求映射作为返回值逻辑视图
1234@RequestMapping("/test/voidTest")public void test(){ System.out.println(this.getClass());}
配置文件的视图前缀 是 /WEB-INF/templates 后缀是.html
10、文件上传和下载
10.1、文件下载
ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文,使用ResponseEntity实现下载文件的功能
<a th:href="@{/test/download}">文件下载测试 </a><br/>
controller方法
1234567891011121314151617181920212223242526272829@RequestMapping("/test/download")public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException { //如果要下载别的文件,区别就是 文件名不一样, 可以直接当做模板 //获取ServletContext对象 ServletContext servletContext = session.getServletContext(); //获取服务器中文件的真实路径 String realPath = servletContext.getRealPath("/static/img/0bd44a2d1fusXjl.jpg"); /*如果不知道分隔符用什么 可以直接用*/ realPath=realPath+ File.separator+"0bd44a2d1fusXjl.jpg"; //创建输入流 InputStream is = new FileInputStream(realPath); //创建字节数组 byte[] bytes = new byte[is.available()]; // is.avail ...













