写在最后
可能有人会问我为什么愿意去花时间帮助大家实现求职梦想,因为我一直坚信时间是可以复制的。我牺牲了自己的大概十个小时写了这片文章,换来的是成千上万的求职者节约几天甚至几周时间浪费在无用的资源上。
上面的这些(算法与数据结构)+(Java多线程学习手册)+(计算机网络顶级教程)等学习资源
中间是个form表单,除了单选和文本域之外,每个元素都需要被前后端校验,前端用jquery的正则表达式,后端用JSR303的hibernate实现
前端:
function validate\_add\_form() {
//拿到要校验的数据
var title = $("#title").val();
var regTitle = /^[\u2E80-\u9FFFa-zA-Z0-9_-]{1,20}$/;
if (!regTitle.test(title)) {
show\_validate\_msg("#title", "error", "请输入1~20个汉字、数字或英文");
return false;
} else {
show\_validate\_msg("#title", "success", "");
}
var price = $("#price").val();
var regPrice = /^(([0-9]{0,5})\.([0-9]{1,2}))$|^([1-9][0-9]{0,4})$/;
if (!regPrice.test(price)) {
show\_validate\_msg("#price", "error", "价格必须是0.1~99999之间");
return false;
} else {
show\_validate\_msg("#price", "success", "");
}
var qq = $("#qq").val();
var regQQ = /^[1-9]\*[1-9][0-9]\*$/;
if (!regQQ.test(qq)) {
show\_validate\_msg("#qq", "error", "请输入正确的QQ号");
return false;
} else {
show\_validate\_msg("#qq", "success", "");
}
var describe = $("#describe").val();
var regDescribe = /^[\u2E80-\u9FFFa-zA-Z0-9_-]{0,200}$/;
if (!regDescribe.test(describe)) {
show\_validate\_msg("#describe", "error", "字数不能超过200字");
return false;
} else {
show\_validate\_msg("#describe", "success", "");
}
if (flag == 0) {
show\_validate\_msg("#group\_pic", "error", "\*请选择一张图片作为物品的封面");
return false;
} else {
show\_validate\_msg("#group\_pic", "success", "");
}
var size = 0;
for(var i=0;i<files.length;i++){
if(files[i].size > 3\*1024\*1024){
show\_validate\_msg("#group\_pic", "error", "\*单个图片大小不能超过3MB");
return false;
} else {
show\_validate\_msg("#group\_pic", "success", "");
size += files[i].size;
}
}
return true;
}
后端:
@Pattern(regexp = "^[\u2E80-\u9FFFa-zA-Z0-9\_-]{1,20}$"
,message = "请输入1~20个汉字、数字或英文")
private String goodsTitle;
@DecimalMin(value = "0.1",message = "价格必须是0.1~99999之间")
@DecimalMax(value = "99999.99",message = "价格必须是0.1~99999之间")
private BigDecimal goodsPrice;
@Pattern(regexp = "^[1-9]\*[1-9][0-9]\*$",message = "请输入正确的QQ号")
private String masterQq;
@Pattern(regexp = "^[\u2E80-\u9FFFa-zA-Z0-9\_-]{0,200}$",message = "字数不能超过200字")
private String goodsDescribe;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
上传图片方式是向数据库中存的是名字的字符串,查询的时候直接与项目路径拼接就行了,以下是我自己写的文件上传删除工具
public class FileHandlerUtil {
public static Boolean uploadFiles(HttpServletRequest request, Goods goods, Integer num,
MultipartFile[] groupImg, Map<String, Object> map) {
StringBuilder stringBuilder = new StringBuilder();
//上传文件
String path = request.getServletContext().getRealPath("/") + "assets\\img\\upload\_pic\_package\\";
try {
String uid, uidSub;
int count = 0;
for (MultipartFile multipartFile : groupImg) {
if (multipartFile.getSize() > 3 \* 1024 \* 1024) {
map.put("imgError", "\*单个图片大小不能超过3MB");
return false;
}
uid = UUID.randomUUID().toString();
uidSub = uid.substring(0, 5);
String fileName = uidSub + ".jpg";
File targetFile = new File(path + fileName);
stringBuilder.append(uidSub).append(',');
multipartFile.transferTo(targetFile);
if (count == num)
goods.setShowImg(uidSub);
count++;
}
System.out.println(stringBuilder);
goods.setGroupImg(stringBuilder.toString().substring(0, stringBuilder.length() - 1));
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
public static Boolean deleteFiles(HttpServletRequest request, Integer id, GoodsService goodsService) {
//删除文件
String path = request.getServletContext().getRealPath("/") + "assets\\img\\upload\_pic\_package\\";
Goods goods = goodsService.getGoodsById(id);
List<String> list = Arrays.asList(goods.getGroupImg().split(","));
try {
for (String fileName : list) {
File targetFile = new File(path + fileName + ".jpg");
if(!targetFile.delete()){
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
ajax提交的代码也放上来了,上传图片的话需要用FormData()这个函数,然后springmvc-servlet还需要配置文件上传解析器,直接去上面我的配置中复制就行了。
$("#add-goods-btn").click(function () {
if (!validate\_add\_form())
return false;
var formData = new FormData($("#add\_goods\_form")[0]);
formData.append('show\_pic', selected_file); //添加图片信息的参数
$.ajax({
url: "${ctp }/addgoods",
type: "POST",
//data: decodeURIComponent($("#add\_goods\_form").serialize()),
data: formData,
contextType: "application/json;charset=utf-8",
dataType: "json",
cache: false, //上传文件不需要缓存
processData: false, //序列化
contentType: false, //内容类型为空
success: function (result) {
if (result.code == 1) {
alert("商品提交成功");
document.getElementById("add\_goods\_form").reset();
window.location.reload(); //刷新页面
} else {
//哪个字段有错就显示哪个字段
if (undefined != result.extend.errorFields.goodsTitle)
show\_validate\_msg("#title", "error", result.extend.errorFields.goodsTitle);
if (undefined != result.extend.errorFields.goodsPrice)
show\_validate\_msg("#price", "error", result.extend.errorFields.goodsPrice);
if (undefined != result.extend.errorFields.masterQq)
show\_validate\_msg("#qq", "error", result.extend.errorFields.masterQq);
if (undefined != result.extend.errorFields.goodsDescribe)
show\_validate\_msg("#describe", "error", result.extend.errorFields.goodsDescribe);
if (undefined != result.extend.errorFields.imgError)
show\_validate\_msg("#group\_pic", "error", result.extend.errorFields.imgError);
}
}
});
return true;
});
最后发一下数据库中的表吧,目前就三张表(两张是物品分类的表),考虑到需要频繁查询,部分的地方就不用第三范式了
最后说一下两个分类的下拉框是发ajax请求动态拼接的,我发的视频教程里有。
3. 浏览物品页面
这一部分代码我是照着教程悟出来的,最上面的是一个导航栏,bootstrap没有自带的导航栏,所以是我自己写的,附上代码
<div class="category-header no-margin-bottom">
<div class="row">
<div class="collapse navbar-collapse filter">
<label class="col-sm-2 control-label">一级分类:</label>
<div class="col-sm-10">
<ul class="nav navbar-nav" id="first\_level\_ul">
</ul>
</div>
</div>
<div class="collapse navbar-collapse filter">
<label class="col-sm-2 control-label">二级分类:</label>
<div class="col-sm-10">
<ul class="nav navbar-nav" id="second\_level\_ul">
</ul>
</div>
</div>
<div class="collapse navbar-collapse filter">
<label class="col-sm-2 control-label">新旧程度</label>
<div class="col-sm-10">
<ul class="nav navbar-nav" id="goods\_degree">
<li value="0"><a class="selected">全部</a></li>
<li value="1"><a href="#">九五新</a></li>
<li value="2"><a href="#">九成新</a></li>
<li value="3"><a href="#">八成新</a></li>
<li value="4"><a href="#">其他</a></li>
</ul>
</div>
</div>
<div class="collapse navbar-collapse filter">
<label class="col-sm-2 control-label">物主性别:</label>
<div class="col-sm-10">
<ul class="nav navbar-nav" id="master\_gender">
<li value="0"><a class="selected">全部</a></li>
<li value="2"><a href="#">男</a></li>
<li value="3"><a href="#">女</a></li>
</ul>
</div>
</div>
<div class="collapse navbar-collapse filter">
<label class="col-sm-2 control-label">交易方式:</label>
<div class="col-sm-10">
<ul class="nav navbar-nav" id="trade\_type">
<li value="0"><a class="selected">全部</a></li>
<li value="1"><a href="#">一口价</a></li>
<li value="2"><a href="#">可砍价</a></li>
<li value="3"><a href="#">拍卖</a></li>
</ul>
</div>
</div>
<div class="collapse navbar-collapse filter">
<label class="col-sm-2 control-label">价格:</label>
<div class="col-sm-10">
<ul class="nav navbar-nav" id="price\_between">
<li value="0"><a class="selected">全部</a></li>
<li value="1"><a href="#">0.1~10</a></li>
<li value="2"><a href="#">10~100</a></li>
<li value="3"><a href="#">100~500</a></li>
<li value="4"><a href="#">500~1000</a></li>
<li value="5"><a href="#">1000~5000</a></li>
<li value="6"><a href="#">5000~10000</a></li>
<li value="7"><a href="#">10000~99999</a></li>
</ul>
</div>
</div>
</div>
</div>
css样式:
.filter{
padding-top: 5px;
}
.filter li{
padding-top: 5px;
padding-left: 5px;
}
.selected{
background-color: #58b325;
color: white;
}
我的逻辑是这样的:一二级分类需要动态拼接,但是一开始进入页面一级分类选中的是全部(值为0,数据库没有0的值,所以查全部),所以不能拼接二级分类,而选中了带值的一级分类之后才开始拼接二级分类,当鼠标点击选中了任何一个筛选项后都需要发ajax请求查询符合条件的物品,而当点击分页条的时候不需要重新发请求,只是查询剩余的物品,解决办法就是在ajax请求中携带筛选项的值,例如:
data: {“pn” : pn, “firstLevelId” : firstLevelId, “secondLevelId” : secondLevelId,
“goodsDegree” : goodsDegree, “masterGender” : masterGender,
“tradeType” : tradeType},
然后通过后端的自动绑定javabean,再通过mybatis的条件查询达到筛选效果
直接上代码,有兴趣自行研究
$(function () {
$('#first\_level\_ul').empty();
$('#first\_level\_ul').append('<li value="0"><a class="selected">全部</a></li>');
$.ajax({
url: "${ctp }/firstlevels",
type: "GET",
contextType: "application/json;charset=utf-8",
dataType: "json",
success: function (result) {
$.each(result.extend.firstlevels, function () {
var aEle = $("<a href='#'></a>").append(this.firstLevelName);
var liEle = $('<li></li>').append(aEle).attr('value', this.firstLevelId);
liEle.appendTo('#first\_level\_ul');
});
getSecondLevel();
}
});
to\_page(1);
});
function getSecondLevel() {
$('#second\_level\_ul').empty();
$('#second\_level\_ul').append('<li value="0"><a class="selected">全部</a></li>');
var firstLevelId = $('#first\_level\_ul a[class=\'selected\']').parent("li").attr('value');
$.ajax({
url: "${ctp }/secondlevels/" + firstLevelId,
type: "GET",
contextType: "application/json;charset=utf-8",
dataType: "json",
success: function (result) {
$.each(result.extend.secondlevels, function () {
var aEle = $('<a href="#"></a>').append(this.secondLevelName);
var liEle = $('<li></li>').append(aEle).attr('value', this.secondLevelId);
liEle.appendTo('#second\_level\_ul');
})
}
})
}
$(document).on("click", "#first\_level\_ul", function () {
getSecondLevel();
});
//为filter下的所有a标签添加单击事件
$(document).on("click", "#filter div[class=\"collapse navbar-collapse filter\"] a", function () {
$(this).parents("ul").children("li").each(function () {
$(this).find("a").removeClass("selected");
});
$(this).addClass("selected");
//alert(ReSelected()); //返回选中结果
to\_page(1)
});
function ReSelected() {
var result = "";
$("#filter a[class='selected']").each(function () {
result += $(this).html() + "\n";
});
return result;
}
function to\_page(pn) {
var firstLevelId = $('#first\_level\_ul a[class=\'selected\']').parent("li").attr('value');
var secondLevelId = $('#second\_level\_ul a[class=\'selected\']').parent("li").attr('value');
var goodsDegree = $('#goods\_degree a[class=\'selected\']').parent("li").attr('value');
var masterGender = $('#master\_gender a[class=\'selected\']').parent("li").attr('value');
var tradeType = $('#trade\_type a[class=\'selected\']').parent("li").attr('value');
$.ajax({
url: "${ctp }/querygoods",
type: "GET",
data: {"pn" : pn, "firstLevelId" : firstLevelId, "secondLevelId" : secondLevelId,
"goodsDegree" : goodsDegree, "masterGender" : masterGender,
"tradeType" : tradeType},
contextType: "application/json;charset=utf-8",
dataType: "json",
success: function (result) {
//商品信息
build\_goods\_table(result);
//分页信息
build\_page\_info(result);
//分页数据
bulid\_page\_nav(result);
}
});
}
@ResponseBody
@RequestMapping("/querygoods")
public Msg querygoods(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Goods goods) {
//分页查询,要查的对象紧跟pageHelper,每次显示10行
//System.out.println(goods);
PageHelper.startPage(pn, 10);
List<Goods> list = goodsService.getAll(goods);
//包装分页结果,每次显示五页
PageInfo<Goods> pageInfo = new PageInfo<>(list, 10);
return Msg.success().add("pageInfo", pageInfo);
}
public List<Goods> getAll(Goods goods) {
GoodsExample example = new GoodsExample();
example.setOrderByClause("goods\_id");
GoodsExample.Criteria criteria = example.createCriteria();
if(goods.getFirstLevelId()!=0){
criteria.andFirstLevelIdEqualTo(goods.getFirstLevelId());
if(goods.getSecondLevelId()!=0 && goods.getSecondLevelId()!=null){
criteria.andSecondLevelIdEqualTo(goods.getSecondLevelId());
}//俄罗斯套娃般的if语句,以后会改善的
}
if(goods.getGoodsDegree()!=0){
criteria.andGoodsDegreeEqualTo(goods.getGoodsDegree());
}
if(goods.getMasterGender()!=0){
criteria.andMasterGenderEqualTo(goods.getMasterGender());
}
if(goods.getTradeType()!=0){
criteria.andTradeTypeEqualTo(goods.getTradeType());
}
return goodsMapper.selectByExampleWithLevelName(example);
}
接下放一段计算物品发布时间的算法,自己写的
var differ;
var nowDate = new Date();
var year = nowDate.getFullYear();
var month = nowDate.getMonth() + 1 < 10 ? "0" + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1;
var date = nowDate.getDate() < 10 ? "0" + nowDate.getDate() : nowDate.getDate();
var hour = nowDate.getHours()< 10 ? "0" + nowDate.getHours() : nowDate.getHours();
var minute = nowDate.getMinutes()< 10 ? "0" + nowDate.getMinutes() : nowDate.getMinutes();
if(year-item.createTime.year>0){
differ=" "+(year-item.createTime.year)+"年前";
}else if(year-item.createTime.year==0&&month-item.createTime.monthValue>0){
differ=" "+(month-item.createTime.monthValue)+"个月前";
}else if(month-item.createTime.monthValue==0&&date-item.createTime.dayOfMonth>0){
differ=" "+(date-item.createTime.dayOfMonth)+"天前"
}else if(date-item.createTime.dayOfMonth==0&&hour-item.createTime.hour>0){
differ=" "+(hour-item.createTime.hour)+"小时前"
}else{
differ=" "+(minute-item.createTime.minute)+"分钟前";
}
4.物品详情页面
如何点击物品标题后查询到的是该物品的信息?道理很简单,就是给a标签的链接带上参数,我做动态拼接的时候这样的:
var titleEle = $('<div class="item-title"></div>').append('<a href="detail?goodsId='+item.goodsId+'">'+'<h4>'+item.goodsTitle+'</h4>'+'</a>');
通过requestParam传参得到id值,再把id值赋给详情页面的控制的中的静态变量,再查询的话返回的就是单条记录了。
@RequestMapping("/detail")
public String detail(Integer goodsId){
detailPageController.goodsId = goodsId;
return "detail";
}
先把id赋给静态变量,并来到详情页面
static Integer goodsId = null;
@ResponseBody
@RequestMapping("/querygoodsbyid")
public Msg querygoodsById() {
//System.out.println(goodsId);
Goods goods = goodsService.getGoodsById(goodsId);
return Msg.success().add("goods", goods);
}
再通过发ajax请求动态拼接数据就行了。
这里也可以通过request域传递id,两种方法都行。
这页还用到了owl-carousel,效果就是把轮播图片一样,前后翻页按钮可以在这上面找到
教程:https://www.cnblogs.com/linjiaxin/p/5960998.html
jquery.flexslider.js中这行代码可以改按钮下边的字
5.物品管理页面
该页面主要用于显示和隐藏用户发布的商品,相当于上架和下架,也可以更新商品和删除商品。
显示和隐藏的方式就是数据库多加一列属性,1为显示,0为隐藏,查询的时候匹配就行
点击修改会弹出模态框,通过更新按钮获取选中的物品id,从而给表格传递不同的值,代码和前面发布页面的类似,点击保存会调用文件工具类的方法,先把之前的图片删除,再存入新的图片。
删除按钮等不说了,看上面发的教程视频就能学会。
以下是java web高级知识:
四、redis作缓存中间件
我通过https://www.bilibili.com/video/av76235738?from=search&seid=2504220265010695682学习了redis的基础知识,这个讲的比较完整,也可以通过https://www.bilibili.com/video/av49517046?from=search&seid=2504220265010695682速学。
我的项目目前需要用redis作缓存来提高查询效率,经测试redis比MySQL查询耗时快四分之三
目前项目需要作缓存的就三个表,一级分类,二级分类以及商品表。
以下是spring整合redis的配置,放在applicationContext.xml中:
<!--设置jedisPool链接池的配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxTotal}"/>
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxWaitMillis" value="${redis.maxWaitMillis}"/>
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"/>
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/>
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<property name="testWhileIdle" value="${redis.testWhileIdle}"/>
</bean>
<!--redis链接密码-->
<bean id="redisPassword" class="org.springframework.data.redis.connection.RedisPassword">
<constructor-arg name="thePassword" value="${redis.password}"/>
</bean>
<!--单一redis连接池-->
<bean id="redisStandaloneConfiguration"
class="org.springframework.data.redis.connection.RedisStandaloneConfiguration">
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="password" ref="redisPassword"/>
<property name="database" value="${redis.database}"/>
</bean>
<!--分片式集群连接池-->
<bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<property name="maxRedirects" value="3"/>
<property name="password" ref="redisPassword"/>
<property name="clusterNodes">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port1}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port2}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port3}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port4}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port5}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port6}"/>
</bean>
</set>
</property>
</bean>
<!--配置jedis链接工厂-->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!--<constructor-arg name="clusterConfig" ref="redisClusterConfig"/>
<constructor-arg name="poolConfig" ref="jedisPoolConfig"/>-->
<constructor-arg name="standaloneConfig" ref="redisStandaloneConfiguration"/>
</bean>
<!--配置jedis模板 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
<!--序列化设置-->
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
</bean>
redis.properties
redis.password=xxx
redis.database=0
# 连接超时时间
redis.timeout=10000
#最大空闲数
redis.maxIdle=20
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
redis.maxTotal=100
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=10000
#连接的最小空闲时间 默认1800000毫秒(30分钟)
redis.minEvictableIdleTimeMillis=300000
#每次释放连接的最大数目,默认3
redis.numTestsPerEvictionRun=1024
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
redis.timeBetweenEvictionRunsMillis=30000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true
*重要:需要在pom.xml加入以下依赖,JSONObject是json格式转换的工具,用了它存入redis时javabean就不用实现序列化接口了,用JSONObject的好处就是jdk8中的LocalDataTime也能以json的格式完美存入redis中
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<!--<version>2.10.2</version>-->
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<!--<version>1.8.23.RELEASE</version>-->
<version>2.2.4.RELEASE</version>
</dependency>
<!-- JSONObject依赖包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
### 最后
**这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档**
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
![image.png](https://img-blog.csdnimg.cn/img_convert/192796491e13c96a6eda9f01e9fa1cdd.webp?x-oss-process=image/format,png)
> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**
**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
ependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
### 最后
**这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档**
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
[外链图片转存中...(img-ReGvpLk4-1715471632718)]
> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**
**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**