面试稿子
面了几次之后,总感觉自己每次说的都不太流利,这里特意写一下自己的面试稿子,到时候照着背吧,还有就是自己准备好一些话术,到时候就可以照着写了
# 先做个自我介绍
面试官你好,我叫XXX,是一名大三的学生,个人信息简历上有,所以就不重复说了,先说一下我的校园经历吧,我大一下学期加入了我们学院的一个物联网的实验室,这个实验室主要是搞物联网硬件开发的,我现在是我们实验室的后端负责人,同时也会负责一些前端界面制作等等。我们实验室会定期参加一些比赛,这期间也做过很多项目,比如智能家居,老人手环,智能门锁,智能垃圾桶,获得了不少项目经验的同时还锻炼了自己的团队合作能力。
然后就是我做的一些项目了,大学期间我主要有四个大项目,前两个我简历上写了,我就不多说了。另外两个第一个是一个在线的网络祭扫平台,这个是一家小公司通过我们学校老师介绍做的一个外包项目,技术栈的话后端采用spring boot,前端使用的是VUE,项目的话由我本人负责,有3个成员协助开发,另外一个的话是我的导师发起的一个老师出卷系统,包括学生端,老师端和管理员端,负责这个项目的大概有10名成员,我是老师端的负责人,技术栈的话前端我们老师端使用了javafx,其他端使用的是vue,后端的话也是spring boot。
在做项目的同时,我也积极参加各种比赛,目前已获得国家级比赛三等奖一项,国家级创新创业项目一项,省级比赛一等奖一项,以及很多校奖。
同时我也是个开源爱好者,我在github上开源了不少项目,也获得了不少star。
好了,大概情况就是这些。
# 介绍一下你的项目
先说一下这个项目创建的动机吧,一开始我是使用的wordpress来写博客,期间我也开源过一款主题,也经过几次版本更新,获得了200多个star,但是使用下来遇到过几个问题,首先就是wordpress是用PHP写的,同时还是国外软件,所以访问后台的时候非常慢,其次就是wordpress主题扩展性有限,有些东西无法实现,最后就是wordpress不方便进行多端开发(PHP是一个被动的,无法主动处理事情,比如聊天功能就很难实习以及一些定时任务),所以我就萌生了开发博客系统的想法。
因为我的定位是多端开发,可扩展性,速度快,所以我首先选择的就是前后分离模式开发,前端我目前开发了H5、微信小程序、安卓APP。后端的话一开始我打算用java的,因为很多大公司都是用java嘛,但是实际调研下来发送java占用内存较大,因为我的服务器只有1核2G,跑一个java应用往往能占80%左右内存,所以最后在权衡之下我使用了go。
然后就是数据库,一开始我选用的是MySQL,但是使用半年下来,发现MySQL有几个问题一是MySQL是结构型的数据库,所以后续要扩展新功能的话就得新建表或者改结构,而且MySQL不方便存储一些数组啊,map类型的数据。另外一个就是我在使用过程中常常会因为外键约束造成数据删除失败,最后就是我觉得MySQL存储一些配置信息不方便,感觉不够快。所以最后我就选用了MongoDB作为博客系统的数据库。我也做过专门的对比测试,发现MongoDB读取速度在1ms以内,MySQL的话第一次在3-4ms左右,后面的话因为有缓存就会快一些。在使用MongoDB后,我就不需要分太多表了,因为MongoDB可以存储一些复杂的数据结构。然后其实我也尝试过使用Redis来缓存一些数据,最后发现没必要,因为多装一个软件会占用大量内存,最后同样使用MongoDB来缓存一些数据了
然后是后端框架选择方面,go的后端框架主要有beego,iris(爱丽丝),gin,echo,revel等,这些框架其实都差不多的,因为我后端主要负责提供接口,所以没必要使用太大的web框架,在经过权衡下,我选择了相对来说更加轻量的echo框架。go的框架使用不算复杂,所以没啥好说的
然后说一下我的三次重构吧,第一次重构是因为我换成MongoDB数据库,第二次重构是因为我发现vue对SEO很不友好,所以我选择了nuxt,这个是一个RSS框架,也是基于vue的,支持后端渲染,对SEO非常友好。第三次重构就是我之前的接口URL和返回的字段写的都比较随意,后面在调用接口时各种不方便,所以最后我就把全部的接口风格都换成了restful的形式。
最后就是项目的一个自动化部署功能,现在我的博客系统运行在docker上,使用nginx反向代理来对外提供数据。说一下具体流程吧,代码修改后之后推送到github上并添加tag,我使用的是阿里云提供的容器镜像服务,阿里云这边可以把代码从github上拉下来,并执行里面的dockfile来构建镜像,构建后之后用户那边只需要开启我之前写的一个小脚本,就可以自动拉取最新镜像来完成更新的功能了。这里说一个技术难点,就是vue项目的构建,因为不用用户的域名是不同的,而我项目的域名文件又在package.json里,在经过技术调用后,最后我采用的环境变量的方式。使用sed+grep+正则 获取文件的配置信息,然后和环境变量进行比对,如果不同的话就把这新的配置信息写入文件,同时重新进行打包构建。
# 介绍一下这个微信公众号平台
这个是一家兼职的公司的项目,主要功能就是企业发布职位信息,然后用户可以完善自己的个人简历,同时可以选择职位并进行投递,然后管理员就可以在后台审核并通知用户入职,用户入职满一个月后就可以领取入职奖励了。
这里主要说一下技术选型吧,因为它们是打算做一个微信公众号平台的,所以我就选择使用uniapp来作为前端了,后端的话因为这个是一个要正式上线的项目,所以我使用的是目前稳定性和生态都很好的java来进行开发,后端框架使用spring boot,数据库的话使用的是MySQL然后使用mybatis来进行操作。
说一下几个技术栈,第一个就是权限认证,因为项目涉及到多个管理员,每个管理员都有不同的权限,最后我使用了SpringSecurity+Thymeleaf的方式来实现权限控制
然后就是部署方便,我们为了实现一键部署,采用的是Jenkins+Docker+GitHub+Maven的方式,我本地写完代码后推送到github,然后jenkins就会自动拉取代码并进行构建部署,然后推送到阿里云的私有镜像仓库,最后服务端就可以直接把代码拉下来。
然后为了加快网站的打开速度,我使用了CDN进行缓存静态资源,然后也考虑过使用nginx进行负载均衡,也进行过技术调研。最后发现没有必要,所以目前只是使用nginx的反向代理来简单代理一下服务器了。
其他的话比如日志,定时任务啥的就不多说了,大概就是这些。
# 在做项目过程中遇到什么问题
# 博客系统
# MongoDB数据库设计问题
这个地方主要就是说明一下MongoDB数据库设计的思路没有必要和MySQL一样,要不然连表查询非常费劲,
比如文章分类还有文章标签,一开始我是打算做成一个单独的标签表和文章联系表,但是后面发现文章id完全可以放入一个数组当中去
# 聊天室设计
这里主要涉及到下面几个问题
一开始我以为协程之间的变量是单独的,所以搞了两个数据库连接池,然后发现数据库链接特别卡。。。
第二个就是websocket链接好后,如何处理请求呢,是每个连接单独处理呢还是有一个线程来统一处理?
同时又涉及到发送消息后如何广播的问题,这里我最后采用的是管道的方案,有一个单独的线程来处理聊天信息,同时维护一个链接的数组,广播时只需要遍历这个数组就可以了
然后还有一个就是历史数据如何获取的问题,我这里采用的是 时间戳的形式这样我们就可以通过直接比较两个数的大小从而非常方便的判断数据
还有就是如何处理返回数据类型问题,我这里主要采用的是json来进行数据的交换
# 爬虫问题
这里其实就是涉及到interface的断言了,因为JSON字符串如果想反序列化的话就必须要写出对应的结构体,但是B博他的数据的接口每次返回的数据都是不对应的,一开始我使用的是正则来进行匹配,但是后面发现获取到正确的数据很麻烦,所以最后我们使用了interface的断言,来进行一步一步的拆分
# 反向代理问题以及如何判断手机端和电脑端
这个其实就是涉及到部署的问题了,因为我想部署我的服务到服务器上,但是问题就是如何用域名来进行访问呢。
而且还要涉及到https的问题,我一开始是打算使用框架自带的来实现,但是会端口占用,所以我后面研究发现了有反向代理这个东西。所以后面我就反向代理了后端端口,然后还可以说一下websocket反向代理的问题,需要自己手动把http协议设置为1.1 因为1.1才支持长连接。
然后下一个就是如何判断当前访问的手机端还是电脑端呢,一开始我打算使用vue来实现,发现是电脑端就自动跳转,但是后面发现这样做效率太低了,所有后面我研究了一下发现nginx就可以做到这个功能,所以我还特地研究了一下nginx的伪静态(原理就是使用正则来匹配agent信息,然后进行重定向操作)
# 数据库空值问题
就是如果发现数据库某个字段为空的话,查找起来发现空值就会报错,所以这次得到的教训就是数据库空值不方便处理,所以尽量不要使用空值
# SQL注入问题
这个的话就可以说一下那次经历,有一个人给我发了一张数据库的截图,然后我就很惊讶,因为我返回的json数据,里面不可能会有数据库的信息,最后还特地去看了相关的视频,用kail的sqlmap来测试了一下,没想到还真的成功了,,,后面我就换成了参数化查询
# 小程序html解析问题
这个主要还是说一下用了一个开源库来实现
# 豆瓣爬虫问题
豆瓣的数据不是json类型的,而是html格式,所以获取数据就非常的困难,一开始打算用正则,但是发现实在太麻烦了,所以最后还是用了一个go的爬虫框架colly,这里可以说一下为了避免阻塞线程我单独开了一个线程来进行操作
# 使用反射
这个地方就是就是讲一下使用反射来获取接口(这个接口实际上是指针)然后来获取里面的值
# 项目结构问题
一开始新建的目录里面引用数据都是相对路径的,后面才发现可以使用go mod来进行包管理
# 如何更新Vue的项目
这里主要就是说一下,在docker里面如何实现vue的更新,因为vue项目的文件是写死在package.json里的,然后不同用户使用的域名又是不同的,如何来实现自动修改和编译呢,一开始我想把package.json文件给暴露出来但是这样很麻烦,而且还不好编译,最后我采用的是环境变量的方式
# 驱动版本问题
就说某次升级MongoDB驱动后发现,接口突然没用了。。。最后才发现是版本问题,好像是新的版本取消了布尔排序的功能。。。。,所以后面我进行了降级处理
# 微信公众号平台
# 权限问题,如何进行权限区分
这个一开始,是打算采用一个权限id来进行判断,但是这样做非常麻烦,所以后面就发现可以使用spring security 来进行权限认证的操作
# spring security 如何自己封装登录接口
自己重写了一系列方法,自己使用自己的加密算法,还有自己的认证逻辑
@Configuration
@EnableWebSecurity
public class Security extends WebSecurityConfigurerAdapter {
UserAuthServiceImpl userAuthServiceImpl;
@Resource
SecurityAccessDeniedHandle securityAccessDeniedHandle;
/**
* 自动注入的推荐方式
* @param userAuthServiceImpl 自己定义的用户安全服务
*/
@Autowired
public void setUserAuthService(UserAuthServiceImpl userAuthServiceImpl) {
this.userAuthServiceImpl = userAuthServiceImpl;
}
@Override
public void configure(WebSecurity web) {
// 过滤掉静态资源,静态资源访问不需要进行权限控制
web.ignoring().antMatchers("/static/**");
// 过滤掉web端的请求
web.ignoring().antMatchers("/api/v1/web/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 允许跨域
// http.cors().disable();
// 暂时全部关闭spring security
// http.csrf().disable().authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
http.headers().frameOptions().disable(); // 允许跨域
// 这里我们单独给每页都设置权限
http.authorizeRequests()
// h5接口
.antMatchers("/api/v1/web/**").permitAll()
.antMatchers("/api/v1/image/**").permitAll()
// 主页
.antMatchers("/").hasAnyRole("1","2","3","4","5")
// 欢迎界面
.antMatchers("/welcome/**").hasAnyRole("1","2","3","4","5")
// 用户管理界面(只有总管理员才有权限)
.antMatchers("/user/**").hasRole("1")
// 财务管理(只有财务管理员和总管理员才有权限)
.antMatchers("/finance/**").hasAnyRole("1","2","5")
// 企业信息管理(企业信息管理员和总管理员)
.antMatchers("/substation/corporate_information/**").hasAnyRole("1","3")
// 职位信息管理(企业信息管理员和总管理员)
.antMatchers("/substation/job_information/**").hasAnyRole("1","3")
// 简历管理(企业管理员和总管理员)
.antMatchers("/substation/resume_manage/**").hasAnyRole("1","4")
// 投递管理(企业管理员和总管理员)
.antMatchers("/substation/delivery_manage/**").hasAnyRole("1","4")
// 入职登记管理(企业管理员和总管理员)
.antMatchers("/substation/entry_registration/**").hasAnyRole("1","4")
// 城市分站和系统信息,只有总管理员才有权限
.antMatchers("/city/**").hasAnyRole("1")
.antMatchers("/system/**").hasAnyRole("1");
// 设置默认的登录页面和登录处理页面以及登录成功后跳转的页面
http.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/")
.defaultSuccessUrl("/")
.loginProcessingUrl("/login");
// 防止网站攻击,get请求不安全,因为页面里面是get请求,而注销是需要post请求所以要关闭这个,所以注销失败的原因就在这
// 关闭csrf避免无法注销
http.csrf().disable();
// 设置登出的接口
http.logout().logoutSuccessUrl("/").deleteCookies().logoutUrl("/login_out").invalidateHttpSession(true);
// 异常处理
http.authorizeRequests()
.and()
.exceptionHandling()
// .authenticationEntryPoint(securityAuthHandle)
.accessDeniedHandler(securityAccessDeniedHandle)
.and();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 这里是用户授权的设置,我们这里自己单独写一个类来处理认证请求,
// 同时我们采用的是自己的加密算法,所以我们自己写一个类来进行加密操作
auth.userDetailsService(userAuthServiceImpl).passwordEncoder(new PBKDF2PasswordEncoder());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
然后这里可以说一下怎么实现用户认证的功能,我们重写一下UserDetailService
@Service
public class UserAuthServiceImpl implements UserDetailsService {
private HttpSession session;
@Autowired
public void setSession(HttpSession session) {
this.session = session;
}
private AdminDao adminDao;
@Autowired
public void setAdminDao(AdminDao adminDao) {
this.adminDao = adminDao;
}
/**
* 用户登录权限认证
* @param s
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
// 个类用来处理用户的登录认证,我们这里可以获取用户名
Admin admin = adminDao.getAdminByUserName(s);
if (admin==null){
throw new AuthenticationCredentialsNotFoundException("用户名不存在");
}
// 这里我们设置session(我们分别设置id,权限,地域等信息)
session.setAttribute("id",admin.getId());
session.setAttribute("authority",admin.getAuthority());
session.setAttribute("area",admin.getAreaId());
// 因为实体类需要继承userDetails,这里为了方便起见我们就直接自己初始化一个userDetails类
// 这里我们设置用户名,密码和用户的权限
return User.withUsername(s).password(admin.getPassword()).roles(""+admin.getAuthority()).build();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 数据库分表问题
自己在设计表的时候过分安装数据库的三范式来进行设计,导致后面查表的时候,使用了非常多的连表查询,甚至一查就是两三个表,所以这个是一个教训,但是因为工期太赶了,所以只能就这样了
# 自动部署问题
这里采用的是jenkins+阿里云镜像来实现自动托管和部署的功能
# 微信token问题
这个主要是微信那边要获取
# 全局异常
因为项目使用接口来返回数据,然而如果接口出错后就会返回html网页导致解析失败,所以就封装了一个全局的异常类
这里使用到了 @ControllerAdvice
注解,这个注解可以处理全局异常,然后还定义了一个异常类,使用枚举类型来返回异常值
# 拦截器认证用户
我们使用 @Configuratio
来配置拦截器,继承WebMvcConfigurer类,然后重写里面的Interceptors方法
@Configuration
public class Auth implements WebMvcConfigurer {
@Resource
AuthInterceptor authInterceptor;
/**
* 添加拦截器,这里我们拦截请求进行权限认证
* @param registry registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor).addPathPatterns().excludePathPatterns("/api/v1/web/auth/**").addPathPatterns("/api/v1/web/auth/user/login/**");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
拦截器我们使用@Component注解
@Component
public class AuthInterceptor implements HandlerInterceptor {
UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// CROS复杂请求时会首先发送一个OPTIONS请求做嗅探,来测试服务器是否支持本次请求,
// 请求成功后才会发送真实的请求;而OPTIONS请求不会携带数据,导致这个请求被拦截了,
// 直接返回了状态码,响应头中没携带解决跨域问题的头部信息,出现了跨域问题。
if(ConstValue.OPTION.equals(request.getMethod().toUpperCase())) {
return true;
}
String id = request.getHeader("id");
String token = request.getHeader("token");
System.out.println(id+"|"+token);
if (id!=null && token!=null){
if(!userService.authUser(Integer.parseInt(id),token)){
throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
}
} else {
throw new BusinessException(ResultCode.PAPAM_IS_BLANK);
}
return true;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# restTemplate的请求乱码问题
我们使用 @Bean
来初始化一个restTemplate对象,里面配置一下编码方式
@Configuration
public class BeanConfig {
/**
* 解决springboot请求乱码的问题
* @return RestTemplate
*/
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 你见过什么设计模式
- 代理模式(就是插件实现那一块,我用的代理来统一转发请求),还有springboot的AOP实现
- 安卓写list view控件的时候,经常用到适配器模式
- 安卓的mvvm架构,用到了观察者模式,观察view model变化
- 工厂模式,可以说一下springboot bean的创建,还有就是线程池,还有就是Retrofit 解析json数据有不同工厂
- 责任链 springsecurity就是用的责任链
- 解释器 比如正则表达式
- 迭代器 遍历数组用的到
- 生成器 比如安卓构建一个dialog
# 你有什么优势与缺点
下面这些虽然有点夸大的成分,但是这东西本身就是一个推销自己的过程,所以要尽可能的扬长避短
优势
项目经验丰富。
大学做过大大小小的项目有10多个,也做过两次外包项目,自己的博客系统也做了快一年了,一直在不断优化
获得了荣誉
参加过国家级,省级,校级的比赛,还有一个国家级的创新创业项目,软件著作权5项,实用新型专利有一项正在申请。也拿到过学校的一等奖学金。
知识面广
前后端都有接触,也会一点硬件开发,语言接触的多,接触过Python,PHP,JavaScript,kotlin,java,go等主流语言,会微信小程序,微信公众号开发,也会安卓开发
对技术这方面很感兴趣,同时喜欢把技术应用于实践中
自己喜欢研究各种新技术,也喜欢把技术用于实践,比如之前给我们寝室做了一个指纹锁,现在还能用,也比如把自己学的各种东西,比如docker,爬虫,cdn,这些都放到自己的博客系统里。还有就是我们把我们的实验室打造成了一个智能的实验室,我们可以通过微信小程序来实现开锁,查看室内温度,开关窗帘和空调的功能。
自学能力强
这些东西基本上都是自学的,大部分东西都是通过看视频,看官方文档,看博客学习的,遇到问题也经常用英文去搜,而不是用中文,或者某个框架遇到问题也直接到github上看issue或者直接提出issue
自制力强,能吃苦
大学室友经常在寝室打游戏,经常睡到10点多,我则每天大概都是7点多起床,每天都是晚上11点去寝室,每天去寝室室友都睡着了,我本人也很少打游戏,大部分时间都在写代码和研究新技术,虽然很累,但是非常享受这个过程。我大概每天至少有12个小时呆在实验室,有时候领导来检查可能会熬夜准备。。。
团队合作经验丰富,有带领团队的经历
我参加的很多项目都是以负责人的身份来参加的,我本人也是我们实验室的后端部分负责人,经常会和团队之间进行讨论,也会给学弟学妹们布置一些任务。同时我也经常和团队之间一起合作做项目,经常使用github等协作软件。
开源精神
我本人非常喜欢逛github,我几乎所有的项目都开源了,我也几乎每天都会推点代码到github上去,看我的github主页可以看到很多绿的记录,我也会在自己使用的一些框架上给开发者提issue,也会在大佬的基础上修改一下代码,比如我不久前就开源了一个安卓的搜索框,那个项目就是在大佬的基础上修改的,适配了androidx也加上了一点自己的小功能
有自己的想法,创意丰富。
比如我最近的博客系统就在研究怎么实现插件功能,我想通过插件功能让我的博客系统实现各种各样的功能,因为我个人的能力是有限的,如果大家一起来进行开发的话就可以打造出一个完整的生态
缺点
很多知识有广度但缺乏深度
我虽然学的非常广,但是我可以明显的感觉到自己学的东西不够深入,比如我很多时候可能想实现什么功能,一般都是直接网上搜,然后粘贴代码的,很多时候因为时间的原因可能不会去深究其中的原理,所以我感觉自己以后还得把某一个领域的东西学深一点
看书看的少
因为我本人很多东西都是直接看视频或者官方文档来学的,很少有时间去看书,但是最近这几个月背了那么多知识点后才发现,基础真的很重要,看了一些基础之后才发现很多东西这样做是有原因的,就比如我当时给我们实验室写的一个监听TCP的操作,当时使用了一个select语句,不知道是干嘛的,现在知道了原来那个东西是监听IO操作的
太宅了
我大部分时间都呆在实验室,很少出去玩,经常只和实验室的人一起交流,缺少和班级之间的交流
实习经历不足
因为本人也没实习过,可能需要一段时间去适应
算法能力还有待提高
因为之前很少接触算法啊,设计模式啊,之类的东西,最近也在进行学习,这东西我感觉很有用,因为最近我研究的插件功能里面就涉及到了设计模式。
# 你有啥兴趣爱好
写博客文章
我大概是从大一下学习就开始写博客了,我的博客网站也运行了快两年了,目前我写了200多篇文章,600多篇文档,目前我网站浏览量也有50多万了,当然我最近也在csdn上写,目前浏览量有4万左右,我之前在知乎上回答了一个问题,最近看了一下有200多万的阅读量。。
做视频
我本人也是从大一下学期暑假开始做UP主的,目前总共发了40多个视频,目前粉丝大概有2900,然后播放量目前有12万,我做的视频主要还是展示自己做的一些开源项目和一些教程类的东西
看番
因为我大部分时间都在研究技术,很少有时间打游戏,我目前唯一的放松方式就是到B站看动漫了。。。偶尔也会看看电影之类的
做硬件,做点小项目
因为我本人非常喜欢动手,所以经常会做一些小制作之类的,比如大一上学期我就做了一个电子钟,有显示时间,计时,闹钟功能。然后大一下学期因为我转专业换寝室,我们寝室是一个大房间,里面三个小房间,新寝室的门没有锁,我后面就干脆自己做了一个指纹锁,把我们室友的指纹都录进去了,后面我们都是每天通过指纹来进行开门操作(当然还可以使用密码)。再有就是我们实验的是智能家居的项目。我们实现了通过微信小程序来实现开锁,查看室内温度,开关窗帘和空调的功能。小程序和服务器后端当时就是全部都是我写的。
# 印象最深刻的一件事
之前知乎发的一篇文章现在已经200多万的阅读量了,我当时是因为写博客写了快半年了,没啥流量,就想着去知乎上去回答问题顺便宣传一下,然后没想到居然火了,当时我特别清楚的记得自己每天起床第一件是就是打开知乎看一下有多少人阅读和点赞,有多少人问问题,然后自己去回答,当时我也创建了几个兴趣交流群,每天都在群里水群,当时也是因为这个原因做了UP主。现在回过头想想,还是很感激这件事的,因为有大家的关注,所以我当时也一直在研究各种新技术,不敢懈怠。才有了现在这么多丰富的经历。现在这个博客系统也是因为有很多人支持,所以我才有动力一直坚持下去,不断重构优化。我觉得,做好一件事不仅需要自己的自制力强,更需要别人的支持和外界的压力刺激才能做的更好。
# 自己最挫败的一件事
高数挂科,因为自己大一是化学专业的,后面转专业后发现高数比我们之前学的更难一点,当时我感觉自己背的差不多了,但是最后还是挂了,当时非常的后悔,晚上甚至都睡不着一直在想这件事情。。。