Youzi的知识库 - 2023年
type: channel
link: https://knowledge.autisn.com/index.php/2023/
description: 关于一个菜鸟的成长过程
items: JVM初认识
items: Nginx的简单使用
items: Thymeleaf的简单使用
items: ElasticSearch在SpringBoot中的简单运用
items: Fegin的调用流程
items: Vue父子组件传值
items: 网站迁移步骤
items: 线程创建常用方式及区别
items: 复习（一）

JVM初认识
type: item
date: 2023-10-24T15:35:05+08:00
description: 1、jvm 内存模型程序计数器 Program Counter Register：记录的是正在执行的虚拟机字节码指令的地址。此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError的区域虚拟机：VM Stack描述的是 JAVA 方法执行的内存模型，每个方法在执行的时候都会创建一个栈帧， 用于存储局部变量表，操作数栈，动态链接，方法接口等信息局部变量表存储了编译期可知的各种基本数据类型、对象引用线程请求的栈深度不够会报 StackOverflowError 异常栈动态扩展的容量不够会报 OutOfMemoryError 异常虚拟机栈是线程隔离的，即每个线程都有自己独立的虚拟机栈本地方法：Native Stack本地方法栈类似于虚拟机栈，只不过本地方法栈使用的是本地方法堆：Heap几乎所有的对象实例都在堆上分配内存2、堆所有的对象实例以及数组都要在堆上分配。堆是垃圾收集器管理的主要区域，也被称为“GC 堆”；也是我们优化最多考虑的地方。 堆可以细分为：1.新生代Eden 空间From Survivor 空间To Survivor 空间2.老年代3.永久代/元空间Java8 以前永久代，受 jvm 管理，java8 以后元空间，直接使用物理内存。因此， 默认情况下，元空间的大小仅受本地内存限制。 垃圾回收从 Java8 开始，HotSpot 已经完全将永久代（Permanent Generation）移除，取而代之的是一 个新的区域—元空间（MetaSpace）3、运行图由于FGC的速度比YGC的速度慢得多，所以JVM的优化也是尽量避免FGC

Nginx的简单使用
type: item
date: 2023-10-24T11:01:00+08:00
description: 1.Docker安装Nginx并启动#没有安装的情况下会自动安装，可以指定版本 docker run -p 80:80 --name nginx -d nginx:1.10 #将容器内的配置文件拷贝到当前目录 #别忘了后面的点 docker container cp nginx:/etc/nginx . #修改文件名称并把这个 conf 移动到/mydata/nginx 下 mv nginx conf #终止原容器 docker stop nginx #执行命令删除原容器 docker rm nginx #创建新的 nginx；执行以下命令 docker run -p 80:80 --name nginx \ -v /mydata/nginx/html:/usr/share/nginx/html \ -v /mydata/nginx/logs:/var/log/nginx \ -v /mydata/nginx/conf:/etc/nginx \ -d nginx:1.10 #给 nginx 的 html 下面放的所有资源可以直接访问 drwxr-xr-x. 3 root root 34 Oct 17 07:49 html2.搭建域名访问要求是 ： 访问gulimall.com 能访问到我们自己本机idea中启动的product服务思路：我们通过配置本地的host域名映射我们虚拟机的中的nginx，然后nginx在根据转发规把请求转发回我们自己的idea中的本地服务。前置说明：因为我们的nginx的安装在云服务器上的，本地Host文件解析域名后访问云服务器, 结果请求被拦截虽然可以用谷歌浏览器安装ModHeader插件解决，但是我们在把请求映射到nginx后，在让nginx转发回我们本地的服务是无法完成的，因为云服务器无法ping通我们本地的ip 原因 本地pc属于移动宽带的内网环境，说白了就是cmd下ipconfig里的ip是你电脑宽带运营商的一个大网络（外网）下的一个内网ip，服务器无法主动与内网ip建立连接，连路由都做不到。所以不可能ping通的。可以考虑使用VPN在您的电脑和服务器之间建立VPN连接，这样服务器和您的电脑就能像在同一个内网一样互相访问了2.1配置本地host可以利用SwitchHost配置工具。需要注意的是这个软件要用管理员打开，然后C:\Windows\System32\drivers\etc把hosts的文件权限放开，才能进行修改如下图配置，前面是虚拟机的地址，后面是需要解析的域名2.2配置nginx# 查看我们nginx的总配置文件 [root@ecs-284198 conf]# cat /mydata/nginx/conf/nginx.conf user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; } [root@ecs-284198 conf]# # 当前总文件的最后一行 include /etc/nginx/conf.d/*.conf; 他会加载这个路径下的所有以 .conf结尾的文件作为配置文件，并且在包含到我们的当前的总配置文件中，这样就不会导致一个配置文件很大，所以接下来我们到 conf.d 的目录下新建一个gulimall.conf文件 # cd 到 /mydata/nginx/conf/conf.d/会有一个default.conf，然后我们复制一个default.conf为gulimall.conf [root@ecs-284198 conf.d]# cd /mydata/nginx/conf/conf.d/ [root@ecs-28…

Thymeleaf的简单使用
type: item
date: 2023-10-24T10:10:45+08:00
description: 1.引入jar包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>2.后端代码package com.atguigu.gulimall.product.web; import com.atguigu.gulimall.product.entity.CategoryEntity; import com.atguigu.gulimall.product.service.CategoryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.List; import java.util.Map; @Controller public class IndexController { @Autowired CategoryService categoryService; @GetMapping({"/", "/index.html"}) public String indexPage(Model model) { //1.查出所有的一级分类 List<CategoryEntity> categoryEntities = categoryService.getLevel1Categorys(); model.addAttribute("categorys", categoryEntities); //视图解析器进行拼串 //"classpath:/templates/" +返回值+ ".html" return "index"; } }3.在resource下新建templates文件夹（页面都放进这里面） 谷粒商城2020 X 家用电器 Hi, 欢迎来到! 登录 注册 新人福利 PLUS会员 促销 公告 更多 全民纸巾大作战 家具建材满999减300元 黑科技冰箱，下单立减千元 抢102减101神券！ 关于召回普利司通（天津）轮胎有限公司2个规格乘用车轮胎的公告 物流推出配送员统一外呼电话"95056” 天府大件运营中心开仓公告 大件物流“送装一体”服务全面升级！ 话费 机票 酒店 游戏 企业购 加油卡 电影票 火车票 众筹 理财 礼品卡 白条 话费 机票 酒店 游戏 X 话费充值 流量充值 套餐变更 号码 面值 100元 20元 50元 10元 2元 ￥98.0-￥100.0 快速充值 抢99减50元话费 X 国际机票 国际/港澳 特惠活动 单程 往返 机票查询 当季热门特惠机票 X 国内港澳台 促销活动 酒店查询 订酒店到 X 点卡 QQ 页游 面值 面值 面值 面值 ￥0.00 直充 卡密 快速充值 吃鸡就要快人一步 4.简单语法示例，更多语法参考官网https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html Welcome to our grocery store! 5.修改Thymeleaf的文件后能及时在页面更新，则要关闭缓存spring: thymeleaf: cache: false6.如果resource下的static文件读取不到时，可以加入以下配置或者在pom文件中加入spring: mvc: static-path-pattern: /static/**或者在pom文件中加入以下配置<resources> <resource> <filtering>false</filtering> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> <include>**/*.yml</include> <include>static/**</include> </includes> </resource> </resources>

ElasticSearch在SpringBoot中的简单运用
type: item
date: 2023-10-23T22:33:00+08:00
description: 1.给es中建立索引。product,建立好映射关系PUT product { "mappings": { "properties": { "skuId": { "type": "long" }, "spuId": { "type": "long" }, "skuTitle": { "type": "text", "analyzer": "ik_smart" }, "skuPrice": { "type": "keyword" }, "skuImg": { "type": "keyword", "index": false, "doc_values": false }, "saleCount": { "type": "long" }, "hosStock": { "type": "boolean" }, "hotScore": { "type": "long" }, "brandId": { "type": "long" }, "catelogId": { "type": "long" }, "brandName": { "type": "keyword", "index": false, "doc_values": false }, "brandImg": { "type": "keyword", "index": false, "doc_values": false }, "catelogName": { "type": "keyword", "index": false, "doc_values": false }, "attrs": { "type": "nested", "properties": { "attrId": { "type": "long" }, "attrName": { "type": "keyword", "index": false, "doc_values": false }, "attrValue": { "type": "keyword" } } } } } }2.Service类package com.atguigu.gulimall.lsearch.service; import com.atguigu.common.to.es.SkuEsModel; import java.io.IOException; import java.util.List; public interface ProductSaveService { boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException; }3.ServiceImpl类package com.atguigu.gulimall.lsearch.service.iml; import com.alibaba.fastjson.JSON; import com.atguigu.common.to.es.SkuEsModel; import com.atguigu.gulimall.lsearch.config.GulimallElasticSearchConfig; import com.atguigu.gulimall.lsearch.constant.EsConstant; import com.atguigu.gulimall.lsearch.service.ProductSaveService; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.xcontent.XContentType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Slf4j @Service("pro…

Fegin的调用流程
type: item
date: 2023-10-23T22:22:00+08:00
description: //Fegin的调用流程 /** 1.构造请求数据，将对象转为JSON * RequestTemplate template = buildTemplateFromArgs,create(argv); * 2.发送请求进行执行《执行成功会解码响应数据): * executeAndDecode(template); * 3.执行请求会有重试机制 * while(true){ * try{ * executeAndDecode(template); * }catch(){ * try{retryer.continueOrpropagate(e);}catch()fthrow ex;) * continue; * } * * } */ //位于ReflectiveFeign.class public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (!"equals".equals(method.getName())) { //判断如果是hashCode或是toString方法就不需要远程调用 if ("hashCode".equals(method.getName())) { return this.hashCode(); } else { //这里是个三元运算符 return "toString".equals(method.getName()) ? this.toString() : //这里才是真正的远程调用，接下来步入这个方法 ((MethodHandler)this.dispatch.get(method)).invoke(args); } ... } //SynchronousMethodHandler.class 代码演示 public Object invoke(Object[] argv) throws Throwable { //请求模板，包含请求路径、请求方式、请求体等信息 //默认构造的模板是不包含请求头和请求参数的 RequestTemplate template = this.buildTemplateFromArgs.create(argv); Options options = this.findOptions(argv); //这是一个重试器，Feign组件默认使用Ribbon的重试机制并增加了根据状态码判断重试机制。默认是关闭的。 Retryer retryer = this.retryer.clone(); while(true) { try { //真正的执行方法在这 return this.executeAndDecode(template, options); } catch (RetryableException var9) { RetryableException e = var9; try { retryer.continueOrPropagate(e); } catch (RetryableException var8) { Throwable cause = var8.getCause(); if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) { throw cause; } throw var8; } if (this.logLevel != Level.NONE) { this.logger.logRetry(this.metadata.configKey(), this.logLevel); } } } }

Vue父子组件传值
type: item
date: 2023-10-01T14:45:28+08:00
description: 子页面 <el-input placeholder="输入关键字进行过滤" v-model="filterText"></el-input> <el-tree :data="menus" :props="defaultProps" node-key="catId" ref="menuTree" @node-click="nodeclick" :filter-node-method="filterNode" :highlight-current="true"></el-tree> <style scoped> 父页面 <el-row :gutter="20"> <el-col :span="6"> <category @tree-node-click="treenodeclick"></category> </el-col> <el-col :span="18"> </el-col> </el-row> <style scoped> 总结：父子组件传递数据子组件给父组件传递数据，事件机制；子组件给父组件发送一个事件，携带上数据。this.$emit("事件名",携带的数据...)

网站迁移步骤
type: item
date: 2023-08-24T11:47:00+08:00
description: 1.安装和原服务器一样的环境1.1我用的是CentOS 系统，首先安装系统环境1.2我使用的是宝塔面板，所以宝塔面板也要安装一致（版本不一致也可以用，不过最好用的是一样的，避免出现未知原因引起的错误）2.迁移前做好备案准备分两种情况在同一个服务器厂商的情况下，只需要把网站的文件迁移到新的服务器（网站文件的路径要和旧服务器的一致）。在不同的服务器厂商的情况下，首先要先进行网站的备案，大概七个工作日，所以不要等到旧服务器快要过期才迁移，这样会导致时间上的不充裕，在迁移过程中会使网站暂停运行，剩下的就是把文件从旧服务器上的文件上传到新的服务器（路径要一致）。3.数据库的迁移在旧服务器上怎么安装的数据库，在新服务器上就怎么安装，最好就是版本都是一样的，然后导出旧数据上的表结构和数据，然后在新服务器上导入，要注意的就是数据库名称和密码要和旧数据库的要一致，这样就方便在新的服务器上运行的时候，不用重新修改代码。4.迁移完成迁移结束后，域名解析要换成新服务器的公网IP，会有缓存，并不是一修改好就马上解析上去的，24-72小时内，所以解析成功后要记得有空看看你的网站能否正常运行。PS1.迁移工具在宝塔面板有一个这个工具，我测试了一下，也是可以迁移成功的2.迁移时图床出现的问题我在迁移过程中是没有发现什么问题，主要是我自己的两个图床工具突然就是上传失败了，完全不能用，报错信息是Call to undefined function think\finfo open()，主要是php中的一个拓展没有安装。2.1找到这个2.2在设置里找到fileinfo并安装2.3重新测试

线程创建常用方式及区别
type: item
date: 2023-04-19T15:59:00+08:00
description: 继承Thread类创建线程//总结：重写的是run()方法，而不是start()方法，但是占用了继承的名额，Java中的类是单继承的 public class MyThread extends Thread{ public static void main(String[] args){ MyThread myThread = new MyThread(); //创建并启动线程 myThread.start(); } @Override public void run(){ //重写run方法 System.out.println("Hello"); } }实现Runnable接口创建线程//总结：实现Runnable接口，实现run()方法，使用依然要用到Thread类，这种方式更常用 //第一种写法 public class MyThread implements Runnable { public static void main(String[] args){ Thread thread = new Thread(new MyThread()); //创建并启动线程 thread.start(); } @Override public void run(){ //重写run方法 System.out.println("Hello"); } } //第二种写法 public class MyThread{ public static void main(String[] args){ Thread thread = new Thread(new Runnable(){ public void run(){ //重写run方法 System.out.println("Hello"); } }); //创建并启动线程 thread.start(); } } //第三种写法 public class MyThread implements Runnable { public static void main(String[] args){ Thread thread = new Thread(()->System.out.println("Hello")); thread.start(); } }使用Callable和Future创建线程//总结：与Runnable的区别在于，Callable可以获取返回结果 //实现Callable接口，实现call()方法，要使用Thread和FutureTask配合，这种方式支持拿到异步执行结果 public class MyThread implements Callable<String> { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> futureTask = new FutureTask<>(new MyThread()); Thread thread = new Thread(futureTask); thread.start(); //此时是获取到的结果 String result = futureTask.get(); System.out.println(result); } @Override public String call() throws Exception { return "Hello"; } }使用线程池例如用Executor框架//总结：实现Callable接口或者实现Runnable接口都可以，由ExecutorService创建线程 public class MyThread implements Runnable { public static void main(String[] args){ // 创建10个数据级的线程池 ExecutorService threadPool = Executors.newFixedThreadPool(10); threadPool.execute(new MyThread()); } @Override public void run(){ System.out.println("Hello"); } }

复习（一）
type: item
date: 2023-03-31T22:51:57+08:00
description: 解决POST、GET请求中文乱码问题解决post请求乱码问题： 在web.xml中配置一个CharacterEncodingFilter过滤器，设置成 utf-8；<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>@RequestMapping(value = "/add", produces = "text/plain;charset=utf-8")get 请求中文参数出现乱码解决方法有两个修改 tomcat 配置文件添加编码与工程编码一致，如下：<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/另外一种方法对参数进行重新编码//ISO8859-1 是 tomcat 默认编码，需要将 tomcat 编码后的内容按 utf-8 编码 String userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1”),“utf-8”)RedisRedis作用内存存储、持久化，放在内存中，断电即失（持久化重要（RDB、AOF））效率高，可以用于告诉缓存发布订阅系统地图信息分析计数器、计数器（浏览量）特性多样的数据类型持久化集群事务基础知识redis默认16个数据库，默认使用第0个，可以使用select进行切换数据库常用命令#查看数据库大小 DBSIZE #查看所有的key KEY * #清空当前数据库 flushdb #清空所有数据库 flushallRedis是单线程的Redis是基于内存操作，所以他的瓶颈在于机器的内存和网络带宽SpringBean的配置详解Bean的实例化配置静态工厂方法实例化Bean实例工厂方法实例化Bean实现FactoryBean规范延迟实例化BeanBean的依赖注入配置依赖注入的两种方式通过Bean的set方法注入<property name="" ref="" /><property name="" value="" />通过构造Bean的方法注入<constructor-arg name="" ref="" /><constructor-arg name="" value="" />ref用于引用其他的Bean的id；value用于注入普通属性值.依赖注入的数据类型有如下三种：普通数据类型，例如：String，int，boolean等，通过value属性指定引用数据类型，例如：UserDaoImpl，DataSource等，通过ref属性指定集合数据类型，例如：List，Map，Properties等Spring 声明式事务无效可能的原因有哪些？答：可能的原因如下：MySQL 使用的是 MyISAM 引擎，而 MyISAM 是不支持事务的；@Transactional 使用在非 public 方法上，@Transactional 注解只能支持 public 级别，其他类型声明的事务不会生效；@Transactional 在同一个类中无事务方法 A() 内部调用有事务方法 B()，那么此时 B() 事物不会生效。Spring 中的 AOP 的底层实现原理是什么？答：Spring AOP 的底层实现原理就是动态代理。Spring AOP 的动态代理有两种实现方式，对于接口使用的是 JDK 自带的动态代理来实现的，而对比非接口使用的是 CGLib 来实现的。Spring 中 Bean 的生命周期答：Spring 中 Bean 的生命周期如下：① 实例化 Bean：对于 BeanFactory 容器，当客户向容器请求一个尚未初始化的 Bean 时，或初始化 Bean 的时候需要注入另一个尚未初始化的依赖时，容器就会调用 createBean 进行实例化。对于 ApplicationContext …