<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[Yu_iChan的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/Yu_iChan</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; Yu_iChan]]></copyright><item><title><![CDATA[黑马点评----＞ 缓存穿透与击穿]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/157128788</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/157128788</guid><author>Yu_iChan</author><pubDate>Mon, 19 Jan 2026 10:16:21 +0800</pubDate><description><![CDATA[首先这个接口是通过店铺id查询店铺信息的，但是redis中的key一般是有前缀的，这个前缀人为定义，并且不同缓存的前缀不一样，因为实现的是通用的缓存穿透问题，所以需要将前缀作为参数。redis中有一个就是很明显的互斥锁，即setnx方法，只有redis中不存在对应key的时候才能成功存储也就是返回1，如果redis中存在对应key，返回的就是0。所以解决方法就是：即便数据库中没有这个data，也要往redis中对应的key存储一个设置了TTL的空值，这样每次请求打过来就不会一直打到数据库上了。]]></description><category></category></item><item><title><![CDATA[Day10 用户端订单模块]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156768708</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156768708</guid><author>Yu_iChan</author><pubDate>Wed, 14 Jan 2026 10:16:26 +0800</pubDate><description><![CDATA[service层的逻辑如何走呢，首先先看下有无异常条件需要判断，比如用户提交的时候没有地址，黑马还让校验购物车是否为空，其实我觉得这里应该是前端该做的事？插入订单之后，该订单还有一个order_detail表里面contain了具体点了什么菜品所以也需要插入这个表，由于要保持二者的事务一致性，所以别忘了加transactional。再来一单的逻辑就是，我们对着一个订单点击再来一单，根据这个订单的下单内容重新填充我们的购物车。跳过了，和第三条历史查询高度重合，简单的查出指定的订单以及detail返回就好了。]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day09 地址簿模块]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156723139</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156723139</guid><author>Yu_iChan</author><pubDate>Thu, 08 Jan 2026 14:50:47 +0800</pubDate><description><![CDATA[所以其实本质就是，最初我们有一个list接口帮助查出所有地址，这个时候前端就拿到了所有地址的id，之后再去点击修改，它会把这个id重新发回后端，我们就能准确到底需要修改的地址并且展示出来以及修改。其实本质是一个update功能，但是由于默认地址只能有一个，当我们设置一个新地址为默认地址之后就需要将其他地址设置为非默认地址。这一块比较简单就是一个表的增删改查，也不涉及别的知识，所以黑马就是带着我们导入了一下代码，所以这里做点简单的解释就过去了。当前我们可能是没有默认地址的，所以需要判别一下。]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day08 购物车功能]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156677277</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156677277</guid><author>Yu_iChan</author><pubDate>Wed, 07 Jan 2026 10:46:34 +0800</pubDate><description><![CDATA[本身就是一个查询操作，这里有一个问题，就是其实系统的用户是有很多的，但是本项目做的是单微信用户，所以其实我们购物车里面有一个usrId，每次查询购物车内容的时候需要通过ThreadLocal得到用户id再送入SQL查询。就只需要给它的number++即可，提一下这里的查询为什么是List<ShoppingCart> 其实根据id和userId找到的肯定只有一个ShoppingCart 其实没多大意义？分情况讨论，如果商品的number是>1的我们只需要修改number即可，反之我们直接删除这条购物车数据。]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day06 微信小程序模块]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156649348</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156649348</guid><author>Yu_iChan</author><pubDate>Tue, 06 Jan 2026 21:04:46 +0800</pubDate><description><![CDATA[没必要看接口了，前端点击了一个category的bottom这个bottom是由前面的分类查询查找出来的，所以会有一个categoryId点了bottom就会将该分类的categoryId传给后端，后端根据分类Id查询菜品，菜品返回给前端的是一个VO对象，这个对象不仅仅包括了菜品的信息，也包括了该菜品的Flavor所以要操作两个表。最后套餐查询有一个特殊的点，就是查询套餐的具体内容，因为一个套餐可以包括多个菜品所以它具备具体的内容，多一个接口。返回的是套餐的list对象，下面是service层的代码。]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day05 店铺状态设置]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156595213</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156595213</guid><author>Yu_iChan</author><pubDate>Mon, 05 Jan 2026 11:13:37 +0800</pubDate><description><![CDATA[配置redis的方式就不说了，在yml文件中配置上host port password即可，这里我用的是docker中的redis注意端口映射！注意的点就是用户端和管理端的RestController记得取别名，不然会重名，spring找不到。请求参数这里仅仅是一个jwt令牌用于确定登录状态~本质上就是查询redis中KEY的value值。这里的KEY统一设置为"SHOP_STATUS"作为redis中的key存入redis。2.用户端仅有一个查询状态，同管理层一样。首先我们需要注入操作redis的对象。]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day04 套餐管理]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156535489</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156535489</guid><author>Yu_iChan</author><pubDate>Sat, 03 Jan 2026 12:35:59 +0800</pubDate><description><![CDATA[所以我们实现的逻辑就是拿到套餐id去查询套餐表，将数据填充至VO中，此时还有setmealdish这个表没有查询，根据前面查询到的setmeal_id去查询得到的是一个List<setmealdish>，同样存入VO中返回给前端！(3) 在2删除完之后我们需要重新插入关联的菜品，这里需要注意的是可能前端没给我们它具体关联的套餐id，所以需要手动赋值，最后调用前面新增套餐时候封装好的insertBatch接口插入表就好了。要把套餐起售首先需要判断套餐里面的菜品是否是起售状态，如果不是则不可以起售套餐。]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day03 公共字段填充与菜品管理 ]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156446170</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156446170</guid><author>Yu_iChan</author><pubDate>Wed, 31 Dec 2025 14:17:47 +0800</pubDate><description><![CDATA[这里是insert操作，所以可以用上我们在前面做的AOP自动填充字段！这里的SQL比较特殊由于Flavor表需要记录dish_id但是这里我们的dish还未存进表里，自己也不清楚id是多少，所以利用动态SQL的操作且SQL中id(auto_increment)功能在插入之后自动将id写入entity中！上述两图表示AOP的自动填充字段，即在执行下方的SQL之前会自动把四个字段填充到dish中...随后执行下方的SQL，执行完后会把自动生成的id也赋给dish..]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day07 缓存菜品与缓存套餐功能]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156429430</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156429430</guid><author>Yu_iChan</author><pubDate>Tue, 30 Dec 2025 20:21:51 +0800</pubDate><description><![CDATA[来到下面<collection 这里的property表示的是DishVO的属性名，但是在DishVO中是List<DishFlavor>也就是这个字段是一对多的，后面的ofType表示就是List存储的对象。(1)新增菜品的时候我们会选择一个category，如果没有即使更新缓存，客户访问的时候由于不走数据库所以会无法查询到新增加的菜品，所以在新增菜品这个操作后我们需要清楚对应category的缓存。首先定义一个 id 后续select中要用到，表明它查出来的需要找到这个Map对应封装。]]></description><category></category></item><item><title><![CDATA[苍穹外卖Day2 分类管理功能]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156414397</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156414397</guid><author>Yu_iChan</author><pubDate>Tue, 30 Dec 2025 10:53:48 +0800</pubDate><description><![CDATA[返回的就是entity数组，所以这里controller的Result中的泛型应该是List<category>，至于为什么是这样就像上面说的前端会根据返回值将id隐藏到选项中，一旦选择了某个菜品分类，就会自动赋值categoryid，像新增菜品中是如何得到categoryid就是这样得到的。从上述图中可以得到，用的PUT方法，并且是用过json传递参数，包括id，name，sort，type四个参数，通常从前端接收用的是DTO，别忘记了@RequestBody。前端传过来的是分类的ID即主键！]]></description><category></category></item><item><title><![CDATA[苍穹外卖day1 员工管理总结]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/156309328</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/156309328</guid><author>Yu_iChan</author><pubDate>Sat, 27 Dec 2025 00:10:01 +0800</pubDate><description><![CDATA[这里需要了解set的作用以及各个属性分别代表什么，比如test中的name就表示对象中封装的属性名字，而中间左边的name表示employee表中的字段，右边还是表示对象封装的属性。这里我们封装了一个LoginDTO的对象用于接收账号密码，将DTO传给Service让他处理，service返回的是employee对象因为在《苍穹外卖》中，虽然 Service 查出来的是 Employee，但 Controller。所有Employee的操作就在这里了，虽然不是很清楚希望会越来越好。]]></description><category></category></item><item><title><![CDATA[二叉排序树]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146438399</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146438399</guid><author>Yu_iChan</author><pubDate>Sat, 22 Mar 2025 13:16:58 +0800</pubDate><description><![CDATA[考察二叉搜索树的插入，例如有2 3 5 现有插入4，需要插入到3，5之间，然后3，5又有可能是3在5上或者5在3上。4总是插入在层次更深的节点下边，所以我们需要开一个map存储层数，顺便由于map是有序的所以插入的时候可以用二分查找到插到哪个数下。]]></description><category></category></item><item><title><![CDATA[二叉树遍历]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146438372</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146438372</guid><author>Yu_iChan</author><pubDate>Sat, 22 Mar 2025 13:13:25 +0800</pubDate><description><![CDATA[同样，本题是给出二叉树的前序遍历和中序遍历求后序遍历，本题由于直接给的就是字符串，所以比给节点值的会好很多，因为不需要哈希表了，string自带了find函数。求后序和求前序本质就是一样的，区别在于输出/更新是在递归之前还是递归之后。]]></description><category></category></item><item><title><![CDATA[前序遍历~]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146438261</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146438261</guid><author>Yu_iChan</author><pubDate>Sat, 22 Mar 2025 13:10:32 +0800</pubDate><description><![CDATA[经典的二叉树遍历，由中序和后序遍历构造出二叉树从而找出前序遍历，但是这种题一般不需要建树，可以直接找到。我们知道后序遍历的最后一个结点就是树的根节点，而根节点在中序遍历中将左右子树分割。利用这一特性我们就可以重建树，而前序遍历是先根后左右。由于题目要输出前序遍历的最后一个数字，所以需要每次递归都进行更新。]]></description><category></category></item><item><title><![CDATA[根能抵达的点]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146300235</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146300235</guid><author>Yu_iChan</author><pubDate>Sun, 16 Mar 2025 19:52:28 +0800</pubDate><description><![CDATA[check如何写呢，check本质就是判断根节点到节点的数目是否不超过Y。本题关键就在代码的实现和二分的思维。本题要求找一个最小的非负整数x，这个x实际就是边权，这里想到二分边权的简直就是天才。我们二分边权然后check一下是否满足条件。]]></description><category></category></item><item><title><![CDATA[判断素数~]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146278182</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146278182</guid><author>Yu_iChan</author><pubDate>Sat, 15 Mar 2025 13:31:05 +0800</pubDate><description><![CDATA[由于n最大只有10000，其实埃氏筛和普通筛都行，但是线性筛最好是背过，所以线性筛后有一个素数数组，由于数组是单调增的所以查找的话可以用二分查找，所以总的时间复杂度是O(n)的非常轻松。这里我们的二分查找应该是查找>=x的第一个数，所以采用lower_bound()]]></description><category></category></item><item><title><![CDATA[二元组整数]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146278107</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146278107</guid><author>Yu_iChan</author><pubDate>Sat, 15 Mar 2025 13:24:33 +0800</pubDate><description><![CDATA[本质就是选两个数，但是要按照字典序输出，也不能要相同的二元组，所以我们想到了排序+去重。]]></description><category></category></item><item><title><![CDATA[链表合并（数组做法）]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146277883</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146277883</guid><author>Yu_iChan</author><pubDate>Sat, 15 Mar 2025 13:02:04 +0800</pubDate><description><![CDATA[拿到题目，两个升序链表要求合并，第一时间想到了归并排序的二路归并，简直是天生为了这个设计的题目。我们没必要管链表，就用数组存也是可以的。二路归并，定义两个指针分别指向两个数组的头部，比较大小，将小的存入新数组，直至一个数组遍历完，后面数组接上就好了。]]></description><category></category></item><item><title><![CDATA[ 删除字符串]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146277851</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146277851</guid><author>Yu_iChan</author><pubDate>Sat, 15 Mar 2025 12:59:35 +0800</pubDate><description><![CDATA[本质就是模拟，删除含有gzu的子串，由于不区分大小写，所以默认将所有的gzu转换成小写进行判断。由于字符串长度不超过100，所以直接遍历就好了，每次取出长度为3的子串进行判断，如果符合的话就跳过，如果不是gzu的话就输出当前遍历到的字符。]]></description><category></category></item><item><title><![CDATA[围圈报数~]]></title><link>https://blog.youkuaiyun.com/Yu_iChan/article/details/146277820</link><guid>https://blog.youkuaiyun.com/Yu_iChan/article/details/146277820</guid><author>Yu_iChan</author><pubDate>Sat, 15 Mar 2025 12:56:21 +0800</pubDate><description><![CDATA[经典的约瑟夫环问题，定义一个队列就可以解决了，由于每次输出的都是报3的人，所以前面两个人先出队，后重新入队，第三个人就出队报数就好了，以此往复，直至队列为空。]]></description><category></category></item></channel></rss>